From 7abed779644ba75a9d8ca1be0afb50b9a30665ad Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 23 Oct 2013 14:45:21 +0200 Subject: [PATCH] tree-vect-patterns.c (vect_recog_divmod_pattern): Optimize sequence based on get_range_info returned range. * tree-vect-patterns.c (vect_recog_divmod_pattern): Optimize sequence based on get_range_info returned range. * gcc.target/i386/vect-div-1.c: New test. From-SVN: r203969 --- gcc/ChangeLog | 5 ++ gcc/testsuite/ChangeLog | 2 + gcc/testsuite/gcc.target/i386/vect-div-1.c | 43 ++++++++++++++++ gcc/tree-vect-patterns.c | 59 ++++++++++++++++------ 4 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/vect-div-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 635dc545ffd..c03246ad8a6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2013-10-23 Jakub Jelinek + + * tree-vect-patterns.c (vect_recog_divmod_pattern): Optimize + sequence based on get_range_info returned range. + 2013-10-23 Andrew MacLeod * tree-ssa.h: Remove all #include's diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b2bd3f552f2..574fdc0f617 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2013-10-23 Jakub Jelinek + * gcc.target/i386/vect-div-1.c: New test. + * gcc.dg/vect/pr58508.c: Remove dg-options. 2013-10-23 Richard Biener diff --git a/gcc/testsuite/gcc.target/i386/vect-div-1.c b/gcc/testsuite/gcc.target/i386/vect-div-1.c new file mode 100644 index 00000000000..b3eed19c7d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-div-1.c @@ -0,0 +1,43 @@ +/* { dg-do compile { target sse2 } } */ +/* { dg-options "-O2 -ftree-vectorize -fno-common -msse2" } */ + +unsigned short b[1024] = { 0 }; +int a[1024] = { 0 }; + +int +f1 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] + 7) / 15; +} + +int +f2 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] + 7) % 15; +} + +int +f3 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] - 66000) / 15; +} + +int +f4 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] - 66000) % 15; +} + +/* In f1 and f2, VRP can prove the first operand of division or modulo + is always non-negative, so there is no need to do >> 31 shift + etc. to check if it is. And in f3 and f4, VRP can prove it is always + negative. */ +/* { dg-final { scan-assembler-not "psrad\[^\n\r\]*\\\$31" } } */ diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index e601baaf626..8d9aaa2303e 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -2230,20 +2230,19 @@ vect_recog_divmod_pattern (vec *stmts, if (post_shift >= prec) return NULL; - /* t1 = oprnd1 h* ml; */ + /* t1 = oprnd0 h* ml; */ t1 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (MULT_HIGHPART_EXPR, t1, oprnd0, build_int_cst (itype, ml)); - append_pattern_def_seq (stmt_vinfo, def_stmt); if (add) { /* t2 = t1 + oprnd0; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); t2 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (PLUS_EXPR, t2, t1, oprnd0); - append_pattern_def_seq (stmt_vinfo, def_stmt); } else t2 = t1; @@ -2251,27 +2250,57 @@ vect_recog_divmod_pattern (vec *stmts, if (post_shift) { /* t3 = t2 >> post_shift; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); t3 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (RSHIFT_EXPR, t3, t2, build_int_cst (itype, post_shift)); - append_pattern_def_seq (stmt_vinfo, def_stmt); } else t3 = t2; - /* t4 = oprnd0 >> (prec - 1); */ - t4 = vect_recog_temp_ssa_var (itype, NULL); - def_stmt - = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0, - build_int_cst (itype, prec - 1)); - append_pattern_def_seq (stmt_vinfo, def_stmt); + double_int oprnd0_min, oprnd0_max; + int msb = 1; + if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE) + { + if (!oprnd0_min.is_negative ()) + msb = 0; + else if (oprnd0_max.is_negative ()) + msb = -1; + } - /* q = t3 - t4; or q = t4 - t3; */ - q = vect_recog_temp_ssa_var (itype, NULL); - pattern_stmt - = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3, - d < 0 ? t3 : t4); + if (msb == 0 && d >= 0) + { + /* q = t3; */ + q = t3; + pattern_stmt = def_stmt; + } + else + { + /* t4 = oprnd0 >> (prec - 1); + or if we know from VRP that oprnd0 >= 0 + t4 = 0; + or if we know from VRP that oprnd0 < 0 + t4 = -1; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); + t4 = vect_recog_temp_ssa_var (itype, NULL); + if (msb != 1) + def_stmt + = gimple_build_assign_with_ops (INTEGER_CST, + t4, build_int_cst (itype, msb), + NULL_TREE); + else + def_stmt + = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0, + build_int_cst (itype, prec - 1)); + append_pattern_def_seq (stmt_vinfo, def_stmt); + + /* q = t3 - t4; or q = t4 - t3; */ + q = vect_recog_temp_ssa_var (itype, NULL); + pattern_stmt + = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3, + d < 0 ? t3 : t4); + } } if (rhs_code == TRUNC_MOD_EXPR)