--- /dev/null
+/* PR tree-optimization/48616 */
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+extern void abort (void);
+int a[4] __attribute__((aligned (32)));
+int b[4] __attribute__((aligned (32)));
+int c[4] __attribute__((aligned (32)));
+int d[4] __attribute__((aligned (32)));
+int e[4] __attribute__((aligned (32)));
+
+__attribute__((noinline, noclone))
+int
+foo (int x)
+{
+ asm ("" : "+r" (x));
+ return x;
+}
+
+__attribute__((noinline, noclone))
+void
+fn1 (int i)
+{
+ a[0] = b[0] << c[0];
+ a[1] = b[1] << c[1];
+ a[2] = b[2] << c[2];
+ a[3] = b[3] << c[3];
+ if (i)
+ {
+ d[0] = e[0] >> c[0];
+ d[1] = e[1] >> c[1];
+ d[2] = e[2] >> c[2];
+ d[3] = e[3] >> c[3];
+ }
+}
+
+__attribute__((noinline, noclone))
+void
+fn2 (int i)
+{
+ a[0] = b[0] << 1;
+ a[1] = b[1] << 2;
+ a[2] = b[2] << 3;
+ a[3] = b[3] << 4;
+ if (i)
+ {
+ d[0] = e[0] >> 1;
+ d[1] = e[1] >> 2;
+ d[2] = e[2] >> 3;
+ d[3] = e[3] >> 4;
+ }
+}
+
+__attribute__((noinline, noclone))
+void
+fn3 (int i, int j)
+{
+ int x = foo (j);
+ a[0] = b[0] << x;
+ a[1] = b[1] << x;
+ a[2] = b[2] << x;
+ a[3] = b[3] << x;
+ if (i)
+ {
+ d[0] = e[0] >> x;
+ d[1] = e[1] >> x;
+ d[2] = e[2] >> x;
+ d[3] = e[3] >> x;
+ }
+}
+
+__attribute__((noinline, noclone))
+void
+fn4 (int i)
+{
+ a[0] = b[0] << 1;
+ a[1] = b[1] << 1;
+ a[2] = b[2] << 1;
+ a[3] = b[3] << 1;
+ if (i)
+ {
+ d[0] = e[0] >> 1;
+ d[1] = e[1] >> 1;
+ d[2] = e[2] >> 1;
+ d[3] = e[3] >> 1;
+ }
+}
+
+int
+main ()
+{
+ int i;
+ int *t;
+ for (i = 0; i < 4; i++)
+ {
+ b[i] = 32;
+ c[i] = i + 1;
+ e[i] = 32;
+ }
+ asm volatile ("" : : "r" (b) : "memory");
+ asm volatile ("" : : "r" (c) : "memory");
+ asm volatile ("" : "=r" (t) : "0" (d) : "memory");
+ fn1 (t != 0);
+ for (i = 0; i < 4; i++)
+ {
+ if (a[i] != (32 << (i + 1)) || d[i] != (32 >> (i + 1)))
+ abort ();
+ a[i] = 0;
+ d[i] = 0;
+ }
+ fn2 (t != 0);
+ for (i = 0; i < 4; i++)
+ {
+ if (a[i] != (32 << (i + 1)) || d[i] != (32 >> (i + 1)))
+ abort ();
+ a[i] = 0;
+ d[i] = 0;
+ }
+ fn3 (t != 0, t != 0);
+ for (i = 0; i < 4; i++)
+ {
+ if (a[i] != (32 << 1) || d[i] != (32 >> 1))
+ abort ();
+ a[i] = 0;
+ d[i] = 0;
+ }
+ fn4 (t != 0);
+ for (i = 0; i < 4; i++)
+ {
+ if (a[i] != (32 << 1) || d[i] != (32 >> 1))
+ abort ();
+ }
+ return 0;
+}
VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
tree vop0, vop1;
unsigned int k;
- bool scalar_shift_arg = false;
+ bool scalar_shift_arg = true;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
int vf;
/* Determine whether the shift amount is a vector, or scalar. If the
shift/rotate amount is a vector, use the vector/vector shift optabs. */
+ if (dt[1] == vect_internal_def && !slp_node)
+ scalar_shift_arg = false;
+ else if (dt[1] == vect_constant_def
+ || dt[1] == vect_external_def
+ || dt[1] == vect_internal_def)
+ {
+ /* In SLP, need to check whether the shift count is the same,
+ in loops if it is a constant or invariant, it is always
+ a scalar shift. */
+ if (slp_node)
+ {
+ VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (slp_node);
+ gimple slpstmt;
+
+ FOR_EACH_VEC_ELT (gimple, stmts, k, slpstmt)
+ if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
+ scalar_shift_arg = false;
+ }
+ }
+ else
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "operand mode requires invariant argument.");
+ return false;
+ }
+
/* Vector shifted by vector. */
- if (dt[1] == vect_internal_def)
+ if (!scalar_shift_arg)
{
optab = optab_for_tree_code (code, vectype, optab_vector);
if (vect_print_dump_info (REPORT_DETAILS))
}
/* See if the machine has a vector shifted by scalar insn and if not
then see if it has a vector shifted by vector insn. */
- else if (dt[1] == vect_constant_def || dt[1] == vect_external_def)
+ else
{
optab = optab_for_tree_code (code, vectype, optab_scalar);
if (optab
&& optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing)
{
- scalar_shift_arg = true;
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "vector/scalar shift/rotate found.");
}
&& (optab_handler (optab, TYPE_MODE (vectype))
!= CODE_FOR_nothing))
{
+ scalar_shift_arg = false;
+
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "vector/vector shift/rotate found.");
}
}
}
- else
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "operand mode requires invariant argument.");
- return false;
- }
/* Supportable by target? */
if (!optab)