--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+int x[4];
+int j[4];
+void foo()
+{
+ x[0] = (x[0] << j[0]) + j[0];
+ x[1] = (x[1] << j[0]) + j[1];
+ x[2] = (x[2] << j[0]) + j[2];
+ x[3] = (x[3] << j[0]) + j[3];
+}
+
+/* The scalar shift argument should be extracted from the available vector. */
+/* { dg-final { scan-tree-dump "BIT_FIELD_REF" "slp2" } } */
+/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" } } */
= (!op1_vectype
|| !tree_nop_conversion_p (TREE_TYPE (vectype),
TREE_TYPE (op1)));
+ if (incompatible_op1_vectype_p
+ && dt[1] == vect_internal_def)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "unusable type for last operand in"
+ " vector/vector shift/rotate.\n");
+ return false;
+ }
}
}
}
{
if (slp_node
&& (!vect_maybe_update_slp_op_vectype (slp_op0, vectype)
- || (!scalar_shift_arg
+ || ((!scalar_shift_arg || dt[1] == vect_internal_def)
&& (!incompatible_op1_vectype_p
|| dt[1] == vect_constant_def)
&& !vect_maybe_update_slp_op_vectype
if (incompatible_op1_vectype_p && !slp_node)
{
+ gcc_assert (!scalar_shift_arg && was_scalar_shift_arg);
op1 = fold_convert (TREE_TYPE (vectype), op1);
if (dt[1] != vect_constant_def)
op1 = vect_init_vector (vinfo, stmt_info, op1,
/* Handle def. */
vec_dest = vect_create_destination_var (scalar_dest, vectype);
- if (scalar_shift_arg)
+ if (scalar_shift_arg && dt[1] != vect_internal_def)
{
/* Vector shl and shr insn patterns can be defined with scalar
operand 2 (shift operand). In this case, use constant or loop
vec_oprnds1.quick_push (vec_oprnd1);
}
}
- else if (slp_node && incompatible_op1_vectype_p)
+ else if (!scalar_shift_arg && slp_node && incompatible_op1_vectype_p)
{
if (was_scalar_shift_arg)
{
FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
{
vop1 = vec_oprnds1[i];
+ /* For internal defs where we need to use a scalar shift arg
+ extract the first lane. */
+ if (scalar_shift_arg && dt[1] == vect_internal_def)
+ {
+ new_temp = make_ssa_name (TREE_TYPE (TREE_TYPE (vop1)));
+ gassign *new_stmt
+ = gimple_build_assign (new_temp,
+ build3 (BIT_FIELD_REF, TREE_TYPE (new_temp),
+ vop1,
+ TYPE_SIZE (TREE_TYPE (new_temp)),
+ bitsize_zero_node));
+ vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+ vop1 = new_temp;
+ }
gassign *new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);