From 49eab32e6e79af5ef80832d058539c8d73a74ef9 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 18 Apr 2011 08:55:13 +0200 Subject: [PATCH] re PR tree-optimization/48616 (-ftree-vectorize -mxop miscompiles right shift) PR tree-optimization/48616 * tree-vect-stmts.c (vectorizable_shift): If SLP, determine whether the shift is by scalar or vector based on whether all SLP scalar stmts have the same rhs. * gcc.dg/pr48616.c: New test. From-SVN: r172638 --- gcc/ChangeLog | 7 ++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/pr48616.c | 134 +++++++++++++++++++++++++++++++++ gcc/tree-vect-stmts.c | 41 +++++++--- 4 files changed, 177 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr48616.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cc3bd641021..5963d44fa9c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-04-18 Jakub Jelinek + + PR tree-optimization/48616 + * tree-vect-stmts.c (vectorizable_shift): If SLP, determine + whether the shift is by scalar or vector based on whether all SLP + scalar stmts have the same rhs. + 2011-04-17 Chung-Lin Tang * config/arm/arm.c (neon_struct_mem_operand): Support POST_INC/PRE_DEC diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 22a33c33281..b95bb3f96a1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-04-18 Jakub Jelinek + + PR tree-optimization/48616 + * gcc.dg/pr48616.c: New test. + 2011-04-18 Tobias Burnus PR fortran/18918 diff --git a/gcc/testsuite/gcc.dg/pr48616.c b/gcc/testsuite/gcc.dg/pr48616.c new file mode 100644 index 00000000000..8c8ec2c146b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr48616.c @@ -0,0 +1,134 @@ +/* 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; +} diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 20ca7a451b4..0c7ab5ada88 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -2077,7 +2077,7 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi, 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; @@ -2159,8 +2159,34 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi, /* 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)) @@ -2168,13 +2194,12 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi, } /* 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."); } @@ -2185,6 +2210,8 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi, && (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."); @@ -2197,12 +2224,6 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi, } } } - else - { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "operand mode requires invariant argument."); - return false; - } /* Supportable by target? */ if (!optab) -- 2.30.2