aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-10-23 14:45:21 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2013-10-23 14:45:21 +0200
commit7abed779644ba75a9d8ca1be0afb50b9a30665ad (patch)
tree82594f08a74d42d571012a398a395645544bcc3a /gcc
parent2d67d16929e583de54d05e1b0d529d48a07ff7e8 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-div-1.c43
-rw-r--r--gcc/tree-vect-patterns.c59
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)