summaryrefslogtreecommitdiff
path: root/gcc/tree-vect-generic.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2012-06-29 16:18:15 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2012-06-29 16:18:15 +0000
commit10dd7335fa297d10c08d7ec9ec8440018e91461b (patch)
treea60d1f6cd77109afc8f7c41317d57566f8f0922a /gcc/tree-vect-generic.c
parente53d55e7b556f38b546938e3a16cf2f8ed1e27d8 (diff)
downloadgcc-10dd7335fa297d10c08d7ec9ec8440018e91461b.tar.gz
Use builtin_widen_mult_even/odd in tree-vect-generic division expansion
* tree-vect-generic.c: Include target.h. (expand_vector_divmod): Use builtin_mul_widen_even/odd if supported. * Makefile.in (tree-vect-generic.o): Update. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@189081 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-vect-generic.c')
-rw-r--r--gcc/tree-vect-generic.c94
1 files changed, 69 insertions, 25 deletions
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index c83db5e1e30..89d8bae99c7 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "ggc.h"
#include "diagnostic.h"
+#include "target.h"
/* Need to include rtl.h, expr.h, etc. for optabs. */
#include "expr.h"
@@ -456,7 +457,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
optab op;
tree *vec;
unsigned char *sel = NULL;
- tree cur_op, mhi, mlo, mulcst, perm_mask, wider_type, tem;
+ tree cur_op, mhi, mlo, mulcst, perm_mask, wider_type, tem, decl_e, decl_o;
if (prec > HOST_BITS_PER_WIDE_INT)
return NULL_TREE;
@@ -745,32 +746,52 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
return NULL_TREE;
op = optab_for_tree_code (MULT_HIGHPART_EXPR, type, optab_default);
- if (op != NULL
- && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
- wider_type = NULL_TREE;
+ if (op != NULL && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
+ wider_type = decl_e = decl_o = NULL_TREE;
else
{
- op = optab_for_tree_code (VEC_WIDEN_MULT_LO_EXPR, type, optab_default);
- if (op == NULL
- || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
- return NULL_TREE;
- op = optab_for_tree_code (VEC_WIDEN_MULT_HI_EXPR, type, optab_default);
- if (op == NULL
- || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
- return NULL_TREE;
- sel = XALLOCAVEC (unsigned char, nunits);
- for (i = 0; i < nunits; i++)
- sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1);
- if (!can_vec_perm_p (TYPE_MODE (type), false, sel))
- return NULL_TREE;
- wider_type
- = build_vector_type (build_nonstandard_integer_type (prec * 2,
- unsignedp),
- nunits / 2);
+ wider_type = build_nonstandard_integer_type (prec * 2, unsignedp),
+ wider_type = build_vector_type (wider_type, nunits / 2);
if (GET_MODE_CLASS (TYPE_MODE (wider_type)) != MODE_VECTOR_INT
|| GET_MODE_BITSIZE (TYPE_MODE (wider_type))
!= GET_MODE_BITSIZE (TYPE_MODE (type)))
return NULL_TREE;
+
+ sel = XALLOCAVEC (unsigned char, nunits);
+
+ if (targetm.vectorize.builtin_mul_widen_even
+ && targetm.vectorize.builtin_mul_widen_odd
+ && (decl_e = targetm.vectorize.builtin_mul_widen_even (type))
+ && (decl_o = targetm.vectorize.builtin_mul_widen_odd (type))
+ && (TYPE_MODE (TREE_TYPE (TREE_TYPE (decl_e)))
+ == TYPE_MODE (wider_type)))
+ {
+ for (i = 0; i < nunits; i++)
+ sel[i] = !BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0);
+ if (!can_vec_perm_p (TYPE_MODE (wider_type), false, sel))
+ decl_e = decl_o = NULL_TREE;
+ }
+ else
+ decl_e = decl_o = NULL_TREE;
+
+ if (decl_e == NULL_TREE)
+ {
+ op = optab_for_tree_code (VEC_WIDEN_MULT_LO_EXPR,
+ type, optab_default);
+ if (op == NULL
+ || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+ return NULL_TREE;
+ op = optab_for_tree_code (VEC_WIDEN_MULT_HI_EXPR,
+ type, optab_default);
+ if (op == NULL
+ || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+ return NULL_TREE;
+
+ for (i = 0; i < nunits; i++)
+ sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1);
+ if (!can_vec_perm_p (TYPE_MODE (type), false, sel))
+ return NULL_TREE;
+ }
}
cur_op = op0;
@@ -816,11 +837,34 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
for (i = 0; i < nunits; i++)
vec[i] = build_int_cst (TREE_TYPE (type), sel[i]);
perm_mask = build_vector (type, vec);
- mhi = gimplify_build2 (gsi, VEC_WIDEN_MULT_HI_EXPR, wider_type,
- cur_op, mulcst);
+
+ if (decl_e != NULL_TREE)
+ {
+ gimple call;
+
+ call = gimple_build_call (decl_e, 2, cur_op, mulcst);
+ mhi = create_tmp_reg (wider_type, NULL);
+ add_referenced_var (mhi);
+ mhi = make_ssa_name (mhi, call);
+ gimple_call_set_lhs (call, mhi);
+ gsi_insert_seq_before (gsi, call, GSI_SAME_STMT);
+
+ call = gimple_build_call (decl_o, 2, cur_op, mulcst);
+ mlo = create_tmp_reg (wider_type, NULL);
+ add_referenced_var (mlo);
+ mlo = make_ssa_name (mlo, call);
+ gimple_call_set_lhs (call, mlo);
+ gsi_insert_seq_before (gsi, call, GSI_SAME_STMT);
+ }
+ else
+ {
+ mhi = gimplify_build2 (gsi, VEC_WIDEN_MULT_HI_EXPR, wider_type,
+ cur_op, mulcst);
+ mlo = gimplify_build2 (gsi, VEC_WIDEN_MULT_LO_EXPR, wider_type,
+ cur_op, mulcst);
+ }
+
mhi = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, mhi);
- mlo = gimplify_build2 (gsi, VEC_WIDEN_MULT_LO_EXPR, wider_type,
- cur_op, mulcst);
mlo = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, mlo);
if (BYTES_BIG_ENDIAN)
cur_op = gimplify_build3 (gsi, VEC_PERM_EXPR, type, mhi, mlo,