Commit 2635892a by Richard Henderson Committed by Richard Henderson

Use VEC_PERM_EXPR in the vectorizer.

        * tree-vect-slp.c: Include langhooks.h.
        (vect_create_mask_and_perm): Emit VEC_PERM_EXPR, not a builtin.
        (vect_transform_slp_perm_load): Use can_vec_perm_expr_p.  Simplify
        mask creation for VEC_PERM_EXPR.
        * tree-vect-stmts.c (perm_mask_for_reverse): Return the mask,
        not the builtin.
        (reverse_vec_elements): Emit VEC_PERM_EXPR not a builtin.
        * Makefile.in (tree-vect-slp.o): Update dependency.
        * optabs.c (can_vec_perm_expr_p): Allow NULL as unknown constant.

From-SVN: r180047
parent f3b3dc6a
2011-10-15 Richard Henderson <rth@redhat.com>
* tree-vect-slp.c: Include langhooks.h.
(vect_create_mask_and_perm): Emit VEC_PERM_EXPR, not a builtin.
(vect_transform_slp_perm_load): Use can_vec_perm_expr_p. Simplify
mask creation for VEC_PERM_EXPR.
* tree-vect-stmts.c (perm_mask_for_reverse): Return the mask,
not the builtin.
(reverse_vec_elements): Emit VEC_PERM_EXPR not a builtin.
* Makefile.in (tree-vect-slp.o): Update dependency.
* optabs.c (can_vec_perm_expr_p): Allow NULL as unknown constant.
2011-10-15 Alan Modra <amodra@gmail.com> 2011-10-15 Alan Modra <amodra@gmail.com>
PR bootstrap/50738 PR bootstrap/50738
...@@ -2753,7 +2753,7 @@ tree-vect-slp.o: tree-vect-slp.c $(CONFIG_H) $(SYSTEM_H) \ ...@@ -2753,7 +2753,7 @@ tree-vect-slp.o: tree-vect-slp.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \ coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
$(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) tree-pretty-print.h \ $(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) tree-pretty-print.h \
gimple-pretty-print.h $(TREE_DATA_REF_H) gimple-pretty-print.h $(TREE_DATA_REF_H) langhooks.h
tree-vect-stmts.o: tree-vect-stmts.c $(CONFIG_H) $(SYSTEM_H) \ tree-vect-stmts.o: tree-vect-stmts.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \ coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
......
...@@ -6686,7 +6686,7 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode) ...@@ -6686,7 +6686,7 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
} }
/* Return true if VEC_PERM_EXPR can be expanded using SIMD extensions /* Return true if VEC_PERM_EXPR can be expanded using SIMD extensions
of the CPU. */ of the CPU. SEL may be NULL, which stands for an unknown constant. */
bool bool
can_vec_perm_expr_p (tree type, tree sel) can_vec_perm_expr_p (tree type, tree sel)
...@@ -6699,10 +6699,10 @@ can_vec_perm_expr_p (tree type, tree sel) ...@@ -6699,10 +6699,10 @@ can_vec_perm_expr_p (tree type, tree sel)
if (!VECTOR_MODE_P (mode)) if (!VECTOR_MODE_P (mode))
return false; return false;
if (TREE_CODE (sel) == VECTOR_CST) if (sel == NULL || TREE_CODE (sel) == VECTOR_CST)
{ {
if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
&& targetm.vectorize.builtin_vec_perm_ok (type, sel)) && (sel == NULL || targetm.vectorize.builtin_vec_perm_ok (type, sel)))
return true; return true;
} }
...@@ -6722,7 +6722,7 @@ can_vec_perm_expr_p (tree type, tree sel) ...@@ -6722,7 +6722,7 @@ can_vec_perm_expr_p (tree type, tree sel)
/* In order to support the lowering of non-constant permutations, /* In order to support the lowering of non-constant permutations,
we need to support shifts and adds. */ we need to support shifts and adds. */
if (TREE_CODE (sel) != VECTOR_CST) if (sel != NULL && TREE_CODE (sel) != VECTOR_CST)
{ {
if (GET_MODE_UNIT_SIZE (mode) > 2 if (GET_MODE_UNIT_SIZE (mode) > 2
&& optab_handler (ashl_optab, mode) == CODE_FOR_nothing && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
......
/* SLP - Basic Block Vectorization /* SLP - Basic Block Vectorization
Copyright (C) 2007, 2008, 2009, 2010 Copyright (C) 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com> Contributed by Dorit Naishlos <dorit@il.ibm.com>
and Ira Rosen <irar@il.ibm.com> and Ira Rosen <irar@il.ibm.com>
...@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h" #include "recog.h"
#include "optabs.h" #include "optabs.h"
#include "tree-vectorizer.h" #include "tree-vectorizer.h"
#include "langhooks.h"
/* Extract the location of the basic block in the source code. /* Extract the location of the basic block in the source code.
Return the basic block location if succeed and NULL if not. */ Return the basic block location if succeed and NULL if not. */
...@@ -2226,8 +2227,7 @@ static inline void ...@@ -2226,8 +2227,7 @@ static inline void
vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt, vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
tree mask, int first_vec_indx, int second_vec_indx, tree mask, int first_vec_indx, int second_vec_indx,
gimple_stmt_iterator *gsi, slp_tree node, gimple_stmt_iterator *gsi, slp_tree node,
tree builtin_decl, tree vectype, tree vectype, VEC(tree,heap) *dr_chain,
VEC(tree,heap) *dr_chain,
int ncopies, int vect_stmts_counter) int ncopies, int vect_stmts_counter)
{ {
tree perm_dest; tree perm_dest;
...@@ -2251,10 +2251,10 @@ vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt, ...@@ -2251,10 +2251,10 @@ vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
second_vec = VEC_index (tree, dr_chain, second_vec_indx); second_vec = VEC_index (tree, dr_chain, second_vec_indx);
/* Generate the permute statement. */ /* Generate the permute statement. */
perm_stmt = gimple_build_call (builtin_decl, perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
3, first_vec, second_vec, mask); first_vec, second_vec, mask);
data_ref = make_ssa_name (perm_dest, perm_stmt); data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_call_set_lhs (perm_stmt, data_ref); gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi); vect_finish_stmt_generation (stmt, perm_stmt, gsi);
/* Store the vector statement in NODE. */ /* Store the vector statement in NODE. */
...@@ -2361,9 +2361,9 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain, ...@@ -2361,9 +2361,9 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
{ {
stmt_vec_info stmt_info = vinfo_for_stmt (stmt); stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree mask_element_type = NULL_TREE, mask_type; tree mask_element_type = NULL_TREE, mask_type;
int i, j, k, m, scale, mask_nunits, nunits, vec_index = 0, scalar_index; int i, j, k, nunits, vec_index = 0, scalar_index;
slp_tree node; slp_tree node;
tree vectype = STMT_VINFO_VECTYPE (stmt_info), builtin_decl; tree vectype = STMT_VINFO_VECTYPE (stmt_info);
gimple next_scalar_stmt; gimple next_scalar_stmt;
int group_size = SLP_INSTANCE_GROUP_SIZE (slp_node_instance); int group_size = SLP_INSTANCE_GROUP_SIZE (slp_node_instance);
int first_mask_element; int first_mask_element;
...@@ -2374,35 +2374,24 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain, ...@@ -2374,35 +2374,24 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
bool mask_fixed = false; bool mask_fixed = false;
bool needs_first_vector = false; bool needs_first_vector = false;
if (!targetm.vectorize.builtin_vec_perm) if (!can_vec_perm_expr_p (vectype, NULL_TREE))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
{ {
fprintf (vect_dump, "no builtin for vect permute for "); fprintf (vect_dump, "no vect permute for ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
} }
return false;
return false;
}
builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
&mask_element_type);
if (!builtin_decl || !mask_element_type)
{
if (vect_print_dump_info (REPORT_DETAILS))
{
fprintf (vect_dump, "no builtin for vect permute for ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
return false;
} }
/* The generic VEC_PERM_EXPR code always uses an integral type of the
same size as the vector element being permuted. */
mask_element_type
= lang_hooks.types.type_for_size
(TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (vectype))), 1);
mask_type = get_vectype_for_scalar_type (mask_element_type); mask_type = get_vectype_for_scalar_type (mask_element_type);
mask_nunits = TYPE_VECTOR_SUBPARTS (mask_type);
mask = (int *) xmalloc (sizeof (int) * mask_nunits);
nunits = TYPE_VECTOR_SUBPARTS (vectype); nunits = TYPE_VECTOR_SUBPARTS (vectype);
scale = mask_nunits / nunits; mask = (int *) xmalloc (sizeof (int) * nunits);
unroll_factor = SLP_INSTANCE_UNROLLING_FACTOR (slp_node_instance); unroll_factor = SLP_INSTANCE_UNROLLING_FACTOR (slp_node_instance);
/* The number of vector stmts to generate based only on SLP_NODE_INSTANCE /* The number of vector stmts to generate based only on SLP_NODE_INSTANCE
...@@ -2425,8 +2414,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain, ...@@ -2425,8 +2414,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
for b's: b0b0b0b1 b1b1b2b2 b2b3b3b3 for b's: b0b0b0b1 b1b1b2b2 b2b3b3b3
... ...
The masks for a's should be: {0,0,0,3} {3,3,6,6} {6,9,9,9} (in target The masks for a's should be: {0,0,0,3} {3,3,6,6} {6,9,9,9}.
scpecific type, e.g., in bytes for Altivec.
The last mask is illegal since we assume two operands for permute The last mask is illegal since we assume two operands for permute
operation, and the mask element values can't be outside that range. operation, and the mask element values can't be outside that range.
Hence, the last mask must be converted into {2,5,5,5}. Hence, the last mask must be converted into {2,5,5,5}.
...@@ -2451,20 +2439,17 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain, ...@@ -2451,20 +2439,17 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
{ {
for (k = 0; k < group_size; k++) for (k = 0; k < group_size; k++)
{ {
first_mask_element = (i + j * group_size) * scale; first_mask_element = i + j * group_size;
for (m = 0; m < scale; m++) if (!vect_get_mask_element (stmt, first_mask_element, 0,
{ nunits, only_one_vec, index,
if (!vect_get_mask_element (stmt, first_mask_element, m, mask, &current_mask_element,
mask_nunits, only_one_vec, index, mask, &need_next_vector,
&current_mask_element, &need_next_vector, &number_of_mask_fixes, &mask_fixed,
&number_of_mask_fixes, &mask_fixed, &needs_first_vector))
&needs_first_vector)) return false;
return false; mask[index++] = current_mask_element;
mask[index++] = current_mask_element;
}
if (index == mask_nunits) if (index == nunits)
{ {
tree mask_vec = NULL; tree mask_vec = NULL;
...@@ -2476,8 +2461,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain, ...@@ -2476,8 +2461,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
mask_vec = build_vector (mask_type, mask_vec); mask_vec = build_vector (mask_type, mask_vec);
index = 0; index = 0;
if (!targetm.vectorize.builtin_vec_perm_ok (vectype, if (!can_vec_perm_expr_p (vectype, mask_vec))
mask_vec))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
{ {
...@@ -2501,7 +2485,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain, ...@@ -2501,7 +2485,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
vect_create_mask_and_perm (stmt, next_scalar_stmt, vect_create_mask_and_perm (stmt, next_scalar_stmt,
mask_vec, first_vec_index, second_vec_index, mask_vec, first_vec_index, second_vec_index,
gsi, node, builtin_decl, vectype, dr_chain, gsi, node, vectype, dr_chain,
ncopies, vect_stmts_counter++); ncopies, vect_stmts_counter++);
} }
} }
......
...@@ -3996,41 +3996,33 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -3996,41 +3996,33 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
} }
/* Given a vector type VECTYPE returns a builtin DECL to be used /* Given a vector type VECTYPE returns a builtin DECL to be used
for vector permutation and stores a mask into *MASK that implements for vector permutation and returns the mask that implements
reversal of the vector elements. If that is impossible to do reversal of the vector elements. If that is impossible to do,
returns NULL (and *MASK is unchanged). */ returns NULL. */
static tree static tree
perm_mask_for_reverse (tree vectype, tree *mask) perm_mask_for_reverse (tree vectype)
{ {
tree builtin_decl; tree mask_element_type, mask_type, mask_vec = NULL;
tree mask_element_type, mask_type; int i, nunits;
tree mask_vec = NULL;
int i;
int nunits;
if (!targetm.vectorize.builtin_vec_perm)
return NULL;
builtin_decl = targetm.vectorize.builtin_vec_perm (vectype, if (!can_vec_perm_expr_p (vectype, NULL_TREE))
&mask_element_type);
if (!builtin_decl || !mask_element_type)
return NULL; return NULL;
mask_element_type
= lang_hooks.types.type_for_size
(TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (vectype))), 1);
mask_type = get_vectype_for_scalar_type (mask_element_type); mask_type = get_vectype_for_scalar_type (mask_element_type);
nunits = TYPE_VECTOR_SUBPARTS (vectype); nunits = TYPE_VECTOR_SUBPARTS (vectype);
if (!mask_type
|| TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
return NULL;
for (i = 0; i < nunits; i++) for (i = 0; i < nunits; i++)
mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec); mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec);
mask_vec = build_vector (mask_type, mask_vec); mask_vec = build_vector (mask_type, mask_vec);
if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec)) if (!can_vec_perm_expr_p (vectype, mask_vec))
return NULL; return NULL;
if (mask)
*mask = mask_vec; return mask_vec;
return builtin_decl;
} }
/* Given a vector variable X, that was generated for the scalar LHS of /* Given a vector variable X, that was generated for the scalar LHS of
...@@ -4041,27 +4033,16 @@ static tree ...@@ -4041,27 +4033,16 @@ static tree
reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi) reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi)
{ {
tree vectype = TREE_TYPE (x); tree vectype = TREE_TYPE (x);
tree mask_vec, builtin_decl; tree mask_vec, perm_dest, data_ref;
tree perm_dest, data_ref;
gimple perm_stmt; gimple perm_stmt;
builtin_decl = perm_mask_for_reverse (vectype, &mask_vec); mask_vec = perm_mask_for_reverse (vectype);
perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype); perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype);
/* Generate the permute statement. */ /* Generate the permute statement. */
perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec); perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
if (!useless_type_conversion_p (vectype, x, x, mask_vec);
TREE_TYPE (TREE_TYPE (builtin_decl))))
{
tree tem = create_tmp_reg (TREE_TYPE (TREE_TYPE (builtin_decl)), NULL);
tem = make_ssa_name (tem, perm_stmt);
gimple_call_set_lhs (perm_stmt, tem);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
perm_stmt = gimple_build_assign (NULL_TREE,
build1 (VIEW_CONVERT_EXPR,
vectype, tem));
}
data_ref = make_ssa_name (perm_dest, perm_stmt); data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_set_lhs (perm_stmt, data_ref); gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi); vect_finish_stmt_generation (stmt, perm_stmt, gsi);
...@@ -4237,7 +4218,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -4237,7 +4218,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
fprintf (vect_dump, "negative step but alignment required."); fprintf (vect_dump, "negative step but alignment required.");
return false; return false;
} }
if (!perm_mask_for_reverse (vectype, NULL)) if (!perm_mask_for_reverse (vectype))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "negative step and reversing not supported."); fprintf (vect_dump, "negative step and reversing not supported.");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment