rs6000.c (map_to_integral_tree_type): New helper function.
authorWill Schmidt <will_schmidt@vnet.ibm.com>
Thu, 11 Oct 2018 21:03:30 +0000 (21:03 +0000)
committerWill Schmidt <willschm@gcc.gnu.org>
Thu, 11 Oct 2018 21:03:30 +0000 (21:03 +0000)
[gcc]

2018-10-09  Will Schmidt <will_schmidt@vnet.ibm.com>

* config/rs6000/rs6000.c (map_to_integral_tree_type): New helper
function.
(fold_mergeeo_helper): New helper function.
(rs6000_gimple_fold_builtin): Add hooks for vec_mergee and vec_mergeo
intrinsics.  Correct some whitespace indentation issues.

From-SVN: r265063

gcc/ChangeLog
gcc/config/rs6000/rs6000.c

index b908601ce03f921e0691734e16f88de47377881d..d6a4cade483f4c99d054903e431838448741a554 100644 (file)
@@ -1,3 +1,11 @@
+2018-10-11  Will Schmidt <will_schmidt@vnet.ibm.com>
+
+       * config/rs6000/rs6000.c (map_to_integral_tree_type): New helper
+       function.
+       (fold_mergeeo_helper): New helper function.
+       (rs6000_gimple_fold_builtin): Add hooks for vec_mergee and vec_mergeo
+       intrinsics.  Correct some whitespace indentation issues.
+
 2018-10-11  Wilco Dijkstra  <wdijkstr@arm.com>
 
        PR target/87511
index 7036fd71c1e0dc26f2db2b6ed1d795ab40411c2e..85b05f6618cef7278c35f3df089dd5dd6cd6e681 100644 (file)
@@ -15238,6 +15238,25 @@ fold_compare_helper (gimple_stmt_iterator *gsi, tree_code code, gimple *stmt)
   gsi_replace (gsi, g, true);
 }
 
+/* Helper function to map V2DF and V4SF types to their
+ integral equivalents (V2DI and V4SI).  */
+tree map_to_integral_tree_type (tree input_tree_type)
+{
+  if (INTEGRAL_TYPE_P (TREE_TYPE (input_tree_type)))
+    return input_tree_type;
+  else
+    {
+      if (types_compatible_p (TREE_TYPE (input_tree_type),
+                             TREE_TYPE (V2DF_type_node)))
+       return V2DI_type_node;
+      else if (types_compatible_p (TREE_TYPE (input_tree_type),
+                                  TREE_TYPE (V4SF_type_node)))
+       return V4SI_type_node;
+      else
+       gcc_unreachable ();
+    }
+}
+
 /* Helper function to handle the vector merge[hl] built-ins.  The
    implementation difference between h and l versions for this code are in
    the values used when building of the permute vector for high word versus
@@ -15260,19 +15279,7 @@ fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high)
      float types, the permute type needs to map to the V2 or V4 type that
      matches size.  */
   tree permute_type;
-  if (INTEGRAL_TYPE_P (TREE_TYPE (lhs_type)))
-    permute_type = lhs_type;
-  else
-    {
-      if (types_compatible_p (TREE_TYPE (lhs_type),
-                             TREE_TYPE (V2DF_type_node)))
-       permute_type = V2DI_type_node;
-      else if (types_compatible_p (TREE_TYPE (lhs_type),
-                                  TREE_TYPE (V4SF_type_node)))
-       permute_type = V4SI_type_node;
-      else
-       gcc_unreachable ();
-    }
+  permute_type = map_to_integral_tree_type (lhs_type);
   tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1);
 
   for (int i = 0; i < midpoint; i++)
@@ -15290,6 +15297,40 @@ fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high)
   gsi_replace (gsi, g, true);
 }
 
+/* Helper function to handle the vector merge[eo] built-ins.  */
+static void
+fold_mergeeo_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_odd)
+{
+  tree arg0 = gimple_call_arg (stmt, 0);
+  tree arg1 = gimple_call_arg (stmt, 1);
+  tree lhs = gimple_call_lhs (stmt);
+  tree lhs_type = TREE_TYPE (lhs);
+  int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type);
+
+  /* The permute_type will match the lhs for integral types.  For double and
+     float types, the permute type needs to map to the V2 or V4 type that
+     matches size.  */
+  tree permute_type;
+  permute_type = map_to_integral_tree_type (lhs_type);
+
+  tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1);
+
+ /* Build the permute vector.  */
+  for (int i = 0; i < n_elts / 2; i++)
+    {
+      elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
+                                    2*i + use_odd));
+      elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
+                                    2*i + use_odd + n_elts));
+    }
+
+  tree permute = elts.build ();
+
+  gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute);
+  gimple_set_location (g, gimple_location (stmt));
+  gsi_replace (gsi, g, true);
+}
+
 /* Fold a machine-dependent built-in in GIMPLE.  (For folding into
    a constant, use rs6000_fold_builtin.)  */
 
@@ -15765,34 +15806,34 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case VSX_BUILTIN_LXVD2X_V2DF:
     case VSX_BUILTIN_LXVD2X_V2DI:
       {
-        arg0 = gimple_call_arg (stmt, 0);  // offset
-        arg1 = gimple_call_arg (stmt, 1);  // address
-        lhs = gimple_call_lhs (stmt);
-        location_t loc = gimple_location (stmt);
-        /* Since arg1 may be cast to a different type, just use ptr_type_node
-           here instead of trying to enforce TBAA on pointer types.  */
-        tree arg1_type = ptr_type_node;
-        tree lhs_type = TREE_TYPE (lhs);
-        /* In GIMPLE the type of the MEM_REF specifies the alignment.  The
-          required alignment (power) is 4 bytes regardless of data type.  */
-        tree align_ltype = build_aligned_type (lhs_type, 4);
-        /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'.  Create
-           the tree using the value from arg0.  The resulting type will match
-           the type of arg1.  */
-        gimple_seq stmts = NULL;
-        tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0);
-        tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+       arg0 = gimple_call_arg (stmt, 0);  // offset
+       arg1 = gimple_call_arg (stmt, 1);  // address
+       lhs = gimple_call_lhs (stmt);
+       location_t loc = gimple_location (stmt);
+       /* Since arg1 may be cast to a different type, just use ptr_type_node
+          here instead of trying to enforce TBAA on pointer types.  */
+       tree arg1_type = ptr_type_node;
+       tree lhs_type = TREE_TYPE (lhs);
+       /* In GIMPLE the type of the MEM_REF specifies the alignment.  The
+         required alignment (power) is 4 bytes regardless of data type.  */
+       tree align_ltype = build_aligned_type (lhs_type, 4);
+       /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'.  Create
+          the tree using the value from arg0.  The resulting type will match
+          the type of arg1.  */
+       gimple_seq stmts = NULL;
+       tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0);
+       tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
                                       arg1_type, arg1, temp_offset);
-        gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
-        /* Use the build2 helper to set up the mem_ref.  The MEM_REF could also
-           take an offset, but since we've already incorporated the offset
-           above, here we just pass in a zero.  */
-        gimple *g;
-        g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr,
-                                               build_int_cst (arg1_type, 0)));
-        gimple_set_location (g, loc);
-        gsi_replace (gsi, g, true);
-        return true;
+       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+       /* Use the build2 helper to set up the mem_ref.  The MEM_REF could also
+          take an offset, but since we've already incorporated the offset
+          above, here we just pass in a zero.  */
+       gimple *g;
+       g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr,
+                                             build_int_cst (arg1_type, 0)));
+       gimple_set_location (g, loc);
+       gsi_replace (gsi, g, true);
+       return true;
       }
 
     /* unaligned Vector stores.  */
@@ -15803,29 +15844,29 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case VSX_BUILTIN_STXVD2X_V2DF:
     case VSX_BUILTIN_STXVD2X_V2DI:
       {
-        arg0 = gimple_call_arg (stmt, 0); /* Value to be stored.  */
-        arg1 = gimple_call_arg (stmt, 1); /* Offset.  */
-        tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address.  */
-        location_t loc = gimple_location (stmt);
-        tree arg0_type = TREE_TYPE (arg0);
-        /* Use ptr_type_node (no TBAA) for the arg2_type.  */
-        tree arg2_type = ptr_type_node;
-        /* In GIMPLE the type of the MEM_REF specifies the alignment.  The
-           required alignment (power) is 4 bytes regardless of data type.  */
-        tree align_stype = build_aligned_type (arg0_type, 4);
-        /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'.  Create
-           the tree using the value from arg1.  */
-        gimple_seq stmts = NULL;
-        tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1);
-        tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+       arg0 = gimple_call_arg (stmt, 0); /* Value to be stored.  */
+       arg1 = gimple_call_arg (stmt, 1); /* Offset.  */
+       tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address.  */
+       location_t loc = gimple_location (stmt);
+       tree arg0_type = TREE_TYPE (arg0);
+       /* Use ptr_type_node (no TBAA) for the arg2_type.  */
+       tree arg2_type = ptr_type_node;
+       /* In GIMPLE the type of the MEM_REF specifies the alignment.  The
+          required alignment (power) is 4 bytes regardless of data type.  */
+       tree align_stype = build_aligned_type (arg0_type, 4);
+       /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'.  Create
+          the tree using the value from arg1.  */
+       gimple_seq stmts = NULL;
+       tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1);
+       tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
                                       arg2_type, arg2, temp_offset);
-        gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
-        gimple *g;
-        g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr,
-                                          build_int_cst (arg2_type, 0)), arg0);
-        gimple_set_location (g, loc);
-        gsi_replace (gsi, g, true);
-        return true;
+       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+       gimple *g;
+       g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr,
+                                        build_int_cst (arg2_type, 0)), arg0);
+       gimple_set_location (g, loc);
+       gsi_replace (gsi, g, true);
+       return true;
       }
 
     /* Vector Fused multiply-add (fma).  */
@@ -15897,35 +15938,34 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case ALTIVEC_BUILTIN_VSPLTISH:
     case ALTIVEC_BUILTIN_VSPLTISW:
       {
-        int size;
-
-         if (fn_code == ALTIVEC_BUILTIN_VSPLTISB)
-           size = 8;
-         else if (fn_code == ALTIVEC_BUILTIN_VSPLTISH)
-           size = 16;
-         else
-           size = 32;
-
-        arg0 = gimple_call_arg (stmt, 0);
-        lhs = gimple_call_lhs (stmt);
-
-        /* Only fold the vec_splat_*() if the lower bits of arg 0 is a
-           5-bit signed constant in range -16 to +15.  */
-        if (TREE_CODE (arg0) != INTEGER_CST
-            || !IN_RANGE (sext_hwi(TREE_INT_CST_LOW (arg0), size),
-                          -16, 15))
-          return false;
-        gimple_seq stmts = NULL;
-        location_t loc = gimple_location (stmt);
-        tree splat_value = gimple_convert (&stmts, loc,
-                                           TREE_TYPE (TREE_TYPE (lhs)), arg0);
-        gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
-        tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value);
-        g = gimple_build_assign (lhs, splat_tree);
-        gimple_set_location (g, gimple_location (stmt));
-        gsi_replace (gsi, g, true);
-        return true;
-       }
+       int size;
+       if (fn_code == ALTIVEC_BUILTIN_VSPLTISB)
+         size = 8;
+       else if (fn_code == ALTIVEC_BUILTIN_VSPLTISH)
+         size = 16;
+       else
+         size = 32;
+
+       arg0 = gimple_call_arg (stmt, 0);
+       lhs = gimple_call_lhs (stmt);
+
+       /* Only fold the vec_splat_*() if the lower bits of arg 0 is a
+          5-bit signed constant in range -16 to +15.  */
+       if (TREE_CODE (arg0) != INTEGER_CST
+           || !IN_RANGE (sext_hwi (TREE_INT_CST_LOW (arg0), size),
+                         -16, 15))
+         return false;
+       gimple_seq stmts = NULL;
+       location_t loc = gimple_location (stmt);
+       tree splat_value = gimple_convert (&stmts, loc,
+                                          TREE_TYPE (TREE_TYPE (lhs)), arg0);
+       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+       tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value);
+       g = gimple_build_assign (lhs, splat_tree);
+       gimple_set_location (g, gimple_location (stmt));
+       gsi_replace (gsi, g, true);
+       return true;
+      }
 
     /* Flavors of vec_splat.  */
     /* a = vec_splat (b, 0x3) becomes a = { b[3],b[3],b[3],...};  */
@@ -15977,8 +16017,8 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case VSX_BUILTIN_VEC_MERGEL_V2DI:
     case VSX_BUILTIN_XXMRGLW_4SF:
     case VSX_BUILTIN_VEC_MERGEL_V2DF:
-       fold_mergehl_helper (gsi, stmt, 1);
-       return true;
+      fold_mergehl_helper (gsi, stmt, 1);
+      return true;
     /* vec_mergeh (integrals).  */
     case ALTIVEC_BUILTIN_VMRGHH:
     case ALTIVEC_BUILTIN_VMRGHW:
@@ -15987,55 +16027,70 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case VSX_BUILTIN_VEC_MERGEH_V2DI:
     case VSX_BUILTIN_XXMRGHW_4SF:
     case VSX_BUILTIN_VEC_MERGEH_V2DF:
-       fold_mergehl_helper (gsi, stmt, 0);
-       return true;
+      fold_mergehl_helper (gsi, stmt, 0);
+      return true;
+
+    /* Flavors of vec_mergee.  */
+    case P8V_BUILTIN_VMRGEW_V4SI:
+    case P8V_BUILTIN_VMRGEW_V2DI:
+    case P8V_BUILTIN_VMRGEW_V4SF:
+    case P8V_BUILTIN_VMRGEW_V2DF:
+      fold_mergeeo_helper (gsi, stmt, 0);
+      return true;
+    /* Flavors of vec_mergeo.  */
+    case P8V_BUILTIN_VMRGOW_V4SI:
+    case P8V_BUILTIN_VMRGOW_V2DI:
+    case P8V_BUILTIN_VMRGOW_V4SF:
+    case P8V_BUILTIN_VMRGOW_V2DF:
+      fold_mergeeo_helper (gsi, stmt, 1);
+      return true;
 
     /* d = vec_pack (a, b) */
     case P8V_BUILTIN_VPKUDUM:
     case ALTIVEC_BUILTIN_VPKUHUM:
     case ALTIVEC_BUILTIN_VPKUWUM:
       {
-       arg0 = gimple_call_arg (stmt, 0);
-       arg1 = gimple_call_arg (stmt, 1);
-       lhs = gimple_call_lhs (stmt);
-       gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1);
-       gimple_set_location (g, gimple_location (stmt));
-       gsi_replace (gsi, g, true);
-       return true;
+       arg0 = gimple_call_arg (stmt, 0);
+       arg1 = gimple_call_arg (stmt, 1);
+       lhs = gimple_call_lhs (stmt);
+       gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1);
+       gimple_set_location (g, gimple_location (stmt));
+       gsi_replace (gsi, g, true);
+       return true;
       }
 
-   /* d = vec_unpackh (a) */
-   /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call
-      in this code is sensitive to endian-ness, and needs to be inverted to
-      handle both LE and BE targets.  */
+    /* d = vec_unpackh (a) */
+    /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call
+       in this code is sensitive to endian-ness, and needs to be inverted to
+       handle both LE and BE targets.  */
     case ALTIVEC_BUILTIN_VUPKHSB:
     case ALTIVEC_BUILTIN_VUPKHSH:
     case P8V_BUILTIN_VUPKHSW:
       {
-       arg0 = gimple_call_arg (stmt, 0);
-       lhs = gimple_call_lhs (stmt);
-       if (BYTES_BIG_ENDIAN)
-        g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
-       else
-        g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
-       gimple_set_location (g, gimple_location (stmt));
-       gsi_replace (gsi, g, true);
-       return true;
+       arg0 = gimple_call_arg (stmt, 0);
+       lhs = gimple_call_lhs (stmt);
+       if (BYTES_BIG_ENDIAN)
+         g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
+       else
+         g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
+       gimple_set_location (g, gimple_location (stmt));
+       gsi_replace (gsi, g, true);
+       return true;
       }
-   /* d = vec_unpackl (a) */
+    /* d = vec_unpackl (a) */
     case ALTIVEC_BUILTIN_VUPKLSB:
     case ALTIVEC_BUILTIN_VUPKLSH:
     case P8V_BUILTIN_VUPKLSW:
       {
-       arg0 = gimple_call_arg (stmt, 0);
-       lhs = gimple_call_lhs (stmt);
-       if (BYTES_BIG_ENDIAN)
-        g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
-       else
-        g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
-       gimple_set_location (g, gimple_location (stmt));
-       gsi_replace (gsi, g, true);
-       return true;
+       arg0 = gimple_call_arg (stmt, 0);
+       lhs = gimple_call_lhs (stmt);
+       if (BYTES_BIG_ENDIAN)
+         g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
+       else
+         g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
+       gimple_set_location (g, gimple_location (stmt));
+       gsi_replace (gsi, g, true);
+       return true;
       }
     /* There is no gimple type corresponding with pixel, so just return.  */
     case ALTIVEC_BUILTIN_VUPKHPX: