diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-10-23 14:45:21 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-10-23 14:45:21 +0200 |
commit | 7abed779644ba75a9d8ca1be0afb50b9a30665ad (patch) | |
tree | 82594f08a74d42d571012a398a395645544bcc3a /gcc | |
parent | 2d67d16929e583de54d05e1b0d529d48a07ff7e8 (diff) | |
download | gcc-7abed779644ba75a9d8ca1be0afb50b9a30665ad.zip gcc-7abed779644ba75a9d8ca1be0afb50b9a30665ad.tar.gz gcc-7abed779644ba75a9d8ca1be0afb50b9a30665ad.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/vect-div-1.c | 43 | ||||
-rw-r--r-- | gcc/tree-vect-patterns.c | 59 |
4 files changed, 94 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 635dc54..c03246a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2013-10-23 Jakub Jelinek <jakub@redhat.com> + + * tree-vect-patterns.c (vect_recog_divmod_pattern): Optimize + sequence based on get_range_info returned range. + 2013-10-23 Andrew MacLeod <amacleod@redhat.com> * tree-ssa.h: Remove all #include's diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b2bd3f5..574fdc0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2013-10-23 Jakub Jelinek <jakub@redhat.com> + * gcc.target/i386/vect-div-1.c: New test. + * gcc.dg/vect/pr58508.c: Remove dg-options. 2013-10-23 Richard Biener <rguenther@suse.de> 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 0000000..b3eed19 --- /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 e601baa..8d9aaa2 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -2230,20 +2230,19 @@ vect_recog_divmod_pattern (vec<gimple> *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<gimple> *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) |