From 93aa3c4aca3647645cd5bce724f9d2126de4b5ea Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 15 Jan 2019 09:11:00 +0100 Subject: [PATCH] re PR tree-optimization/88775 (Optimize std::string assignment) PR tree-optimization/88775 * match.pd (cmp (convert1?@2 addr@0) (convert2? addr@1)): Optimize equal == 0 equality pointer comparisons some more if compared in integral types and either one points to an automatic var and the other to a global, or we can prove at least one points to the middle or both point to start or both point to end. * gcc.dg/tree-ssa/pr88775-1.c: New test. * gcc.dg/tree-ssa/pr88775-2.c: New test. From-SVN: r267931 --- gcc/ChangeLog | 9 +++ gcc/match.pd | 62 +++++++++++++++---- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c | 73 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c | 43 +++++++++++++ 5 files changed, 183 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 03667c8d97f..c350d1cec0f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-01-15 Jakub Jelinek + + PR tree-optimization/88775 + * match.pd (cmp (convert1?@2 addr@0) (convert2? addr@1)): Optimize + equal == 0 equality pointer comparisons some more if compared in + integral types and either one points to an automatic var and the + other to a global, or we can prove at least one points to the middle + or both point to start or both point to end. + 2019-01-14 Andi Kleen * Makefile.in: Lower autofdo sampling rate by 10x. diff --git a/gcc/match.pd b/gcc/match.pd index 60b12f94f9e..bccf4df05a2 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3896,6 +3896,52 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) || TREE_CODE (base1) == SSA_NAME || TREE_CODE (base1) == STRING_CST)) equal = (base0 == base1); + if (equal == 0) + { + if (!DECL_P (base0) || !DECL_P (base1)) + equal = 2; + else if (cmp != EQ_EXPR && cmp != NE_EXPR) + equal = 2; + /* If this is a pointer comparison, ignore for now even + valid equalities where one pointer is the offset zero + of one object and the other to one past end of another one. */ + else if (!INTEGRAL_TYPE_P (TREE_TYPE (@2))) + ; + /* Assume that automatic variables can't be adjacent to global + variables. */ + else if (is_global_var (base0) != is_global_var (base1)) + ; + else + { + tree sz0 = DECL_SIZE_UNIT (base0); + tree sz1 = DECL_SIZE_UNIT (base1); + /* If sizes are unknown, e.g. VLA or not representable, + punt. */ + if (!tree_fits_poly_int64_p (sz0) + || !tree_fits_poly_int64_p (sz1)) + equal = 2; + else + { + poly_int64 size0 = tree_to_poly_int64 (sz0); + poly_int64 size1 = tree_to_poly_int64 (sz1); + /* If one offset is pointing (or could be) to the beginning + of one object and the other is pointing to one past the + last byte of the other object, punt. */ + if (maybe_eq (off0, 0) && maybe_eq (off1, size1)) + equal = 2; + else if (maybe_eq (off1, 0) && maybe_eq (off0, size0)) + equal = 2; + /* If both offsets are the same, there are some cases + we know that are ok. Either if we know they aren't + zero, or if we know both sizes are no zero. */ + if (equal == 2 + && known_eq (off0, off1) + && (known_ne (off0, 0) + || (known_ne (size0, 0) && known_ne (size1, 0)))) + equal = 0; + } + } + } } (if (equal == 1 && (cmp == EQ_EXPR || cmp == NE_EXPR @@ -3918,16 +3964,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { constant_boolean_node (known_ge (off0, off1), type); }) (if (cmp == GT_EXPR && (known_gt (off0, off1) || known_le (off0, off1))) { constant_boolean_node (known_gt (off0, off1), type); })) - (if (equal == 0 - && DECL_P (base0) && DECL_P (base1) - /* If we compare this as integers require equal offset. */ - && (!INTEGRAL_TYPE_P (TREE_TYPE (@2)) - || known_eq (off0, off1))) - (switch - (if (cmp == EQ_EXPR) - { constant_boolean_node (false, type); }) - (if (cmp == NE_EXPR) - { constant_boolean_node (true, type); }))))))))) + (if (equal == 0) + (switch + (if (cmp == EQ_EXPR) + { constant_boolean_node (false, type); }) + (if (cmp == NE_EXPR) + { constant_boolean_node (true, type); }))))))))) /* Simplify pointer equality compares using PTA. */ (for neeq (ne eq) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 20c212c267a..810c45780a7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-01-15 Jakub Jelinek + + PR tree-optimization/88775 + * gcc.dg/tree-ssa/pr88775-1.c: New test. + * gcc.dg/tree-ssa/pr88775-2.c: New test. + 2019-01-14 Marek Polacek PR c++/88825 - ICE with bogus function return type deduction. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c new file mode 100644 index 00000000000..779b2b78300 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c @@ -0,0 +1,73 @@ +/* PR tree-optimization/88775 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "return 1;" 10 "optimized" } } */ + +int a[64] = {}; +int b[64] = {}; + +int +f1 (void) +{ + return (__UINTPTR_TYPE__) &a[2] != (__UINTPTR_TYPE__) &b[2]; +} + +int +f2 (void) +{ + return (__UINTPTR_TYPE__) &a[2] != (__UINTPTR_TYPE__) &b[10]; +} + +int +f3 (void) +{ + return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &b[0]; +} + +int +f4 (void) +{ + return (__UINTPTR_TYPE__) &a[64] != (__UINTPTR_TYPE__) &b[64]; +} + +int +f5 (void) +{ + int c[64] = {}; + return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &c[64]; +} + +int +f6 (void) +{ + int c[64] = {}; + return (__UINTPTR_TYPE__) &b[64] != (__UINTPTR_TYPE__) &c[0]; +} + +int +f7 (void) +{ + int c[64] = {}, d[64] = {}; + return (__UINTPTR_TYPE__) &c[2] != (__UINTPTR_TYPE__) &d[2]; +} + +int +f8 (void) +{ + int c[64] = {}, d[64] = {}; + return (__UINTPTR_TYPE__) &c[2] != (__UINTPTR_TYPE__) &d[10]; +} + +int +f9 (void) +{ + int c[64] = {}, d[64] = {}; + return (__UINTPTR_TYPE__) &c[0] != (__UINTPTR_TYPE__) &d[0]; +} + +int +f10 (void) +{ + int c[64] = {}, d[64] = {}; + return (__UINTPTR_TYPE__) &c[64] != (__UINTPTR_TYPE__) &d[64]; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c new file mode 100644 index 00000000000..292ce6edefc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c @@ -0,0 +1,43 @@ +/* PR tree-optimization/88775 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* These can't be decided until we know how the variables will + be laid out in memory. */ +/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */ + +int a[64] = {}; +int b[64] = {}; +int e[0] = {}; +int f[0] = {}; + +int +f1 (void) +{ + return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &b[64]; +} + +int +f2 (void) +{ + return (__UINTPTR_TYPE__) &a[64] != (__UINTPTR_TYPE__) &b[0]; +} + +int +f3 (void) +{ + return (__UINTPTR_TYPE__) &e[0] != (__UINTPTR_TYPE__) &f[0]; +} + +int +f4 (void) +{ + int c[64] = {}, d[64] = {}; + return (__UINTPTR_TYPE__) &c[0] != (__UINTPTR_TYPE__) &d[64]; +} + +int +f5 (void) +{ + int c[64] = {}, d[64] = {}; + return (__UINTPTR_TYPE__) &c[64] != (__UINTPTR_TYPE__) &d[0]; +} -- 2.30.2