Fix wrong code with pure functions

I introduced bug into find_func_aliases_for_call in handling pure functions.
Instead of reading global memory pure functions are believed to write global
memory.  This results in misoptimization of the testcase at -O1.

The change to pta-callused.c updates the template for new behaviour of the
constraint generation. We copy nonlocal memory to calluse which is correct but
also not strictly necessary because later we take care to add nonlocal_p flag
manually.

gcc/ChangeLog:

	PR tree-optimization/103209
	* tree-ssa-structalias.c (find_func_aliases_for_call): Fix
	use of handle_rhs_call

gcc/testsuite/ChangeLog:

	PR tree-optimization/103209
	* gcc.dg/tree-ssa/pta-callused.c: Update template.
	* gcc.c-torture/execute/pr103209.c: New test.
This commit is contained in:
Jan Hubicka 2021-11-12 23:55:50 +01:00
parent 264f061997
commit 4d2d5565a0
3 changed files with 38 additions and 2 deletions

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdint.h>
int32_t a[6];
int64_t b;
int32_t *c;
int32_t **d = &c;
int64_t *e = &b;
int32_t **const *f = &d;
int32_t **const **g = &f;
int32_t *h();
static int16_t j();
static uint32_t k(int8_t, const int32_t *, int64_t);
static uint32_t l() {
int32_t *m = &a[3];
int32_t n = 0;
int8_t o = 0;
int32_t *p[] = {&n, &n, &n, &n};
uint32_t q[6][1][2] = {};
for (o = 0; o <= 1; o = 6)
if (h(j(k(3, 0, q[2][0][0]), &n), n) == p[3])
*m = *e;
return 0;
}
int32_t *h(uint32_t, int32_t) { return ***g; }
int16_t j(uint32_t, int32_t *r) { **f = r; return 0;}
uint32_t k(int8_t, const int32_t *, int64_t) { *e = 3; return 0;}
int main() {
int i = 0;
l();
for (i = 0; i < 6; i++){
if (i == 3 && a[i] != 3)
__builtin_abort ();
}
return 0;
}

View File

@ -22,5 +22,5 @@ int bar (int b)
return *foo (&q);
}
/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { NONLOCAL f.* i q }" "alias" } } */
/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { ESCAPED NONLOCAL f.* i q }" "alias" } } */

View File

@ -4996,7 +4996,7 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
reachable from their arguments, but they are not an escape
point for reachable memory of their arguments. */
else if (flags & (ECF_PURE|ECF_LOOPING_CONST_OR_PURE))
handle_rhs_call (t, &rhsc, implicit_pure_eaf_flags, true, false);
handle_rhs_call (t, &rhsc, implicit_pure_eaf_flags, false, true);
/* If the call is to a replaceable operator delete and results
from a delete expression as opposed to a direct call to
such operator, then the effects for PTA (in particular