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
This commit is contained in:
Jakub Jelinek 2019-01-15 09:11:00 +01:00 committed by Jakub Jelinek
parent 6facd01f98
commit 93aa3c4aca
5 changed files with 183 additions and 10 deletions

View File

@ -1,3 +1,12 @@
2019-01-15 Jakub Jelinek <jakub@redhat.com>
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 <ak@linux.intel.com>
* Makefile.in: Lower autofdo sampling rate by 10x.

View File

@ -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)

View File

@ -1,3 +1,9 @@
2019-01-15 Jakub Jelinek <jakub@redhat.com>
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 <polacek@redhat.com>
PR c++/88825 - ICE with bogus function return type deduction.

View File

@ -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];
}

View File

@ -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];
}