re PR tree-optimization/77648 (Setting conversion to a integer to double to 0 3/4 through a loop)

2016-09-21  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/77648
	* tree-ssa-structalias.c (process_constraint): Handle all DEREF
	with complex RHS.
	(make_transitive_closure_constraints): Adjust comment.
	(make_any_offset_constraints): New function.
	(handle_rhs_call): Make sure to first expand a pointer to all
	subfields before transitively closing it.
	(handle_const_call): Likewise.  Properly expand returned
	pointers as well.
	(handle_pure_call): Likewise.

	* gcc.dg/torture/pr77648-1.c: New testcase.
	* gcc.dg/torture/pr77648-2.c: Likewise.

From-SVN: r240303
This commit is contained in:
Richard Biener 2016-09-21 07:38:33 +00:00 committed by Richard Biener
parent f955c4c483
commit 6811ea7976
5 changed files with 107 additions and 16 deletions

View File

@ -1,3 +1,16 @@
2016-09-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/77648
* tree-ssa-structalias.c (process_constraint): Handle all DEREF
with complex RHS.
(make_transitive_closure_constraints): Adjust comment.
(make_any_offset_constraints): New function.
(handle_rhs_call): Make sure to first expand a pointer to all
subfields before transitively closing it.
(handle_const_call): Likewise. Properly expand returned
pointers as well.
(handle_pure_call): Likewise.
2016-09-21 Richard Biener <rguenther@suse.de>
Jakub Jelinek <jakub@redhat.com>

View File

@ -1,3 +1,9 @@
2016-09-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/77648
* gcc.dg/torture/pr77648-1.c: New testcase.
* gcc.dg/torture/pr77648-2.c: Likewise.
2016-09-21 Richard Biener <rguenther@suse.de>
Jakub Jelinek <jakub@redhat.com>

View File

@ -0,0 +1,24 @@
/* { dg-do run } */
struct S { int *p; int *q; };
int **__attribute__((noinline,noclone,pure)) foo (struct S *s)
{
int tem;
__asm__ ("" : "=g" (tem) : "g" (s->p));
return &s->q;
}
int main()
{
struct S s;
int i = 1, j = 2;
int **x;
s.p = &i;
s.q = &j;
x = foo (&s);
**x = 7;
if (j != 7)
__builtin_abort ();
return 0;
}

View File

@ -0,0 +1,22 @@
/* { dg-do run } */
struct S { int *p; int *q; };
int **__attribute__((noinline,noclone,const)) foo (struct S *s)
{
return &s->q;
}
int main()
{
struct S s;
int i = 1, j = 2;
int **x;
s.p = &i;
s.q = &j;
x = foo (&s);
**x = 7;
if (j != 7)
__builtin_abort ();
return 0;
}

View File

@ -3010,7 +3010,7 @@ process_constraint (constraint_t t)
process_constraint (new_constraint (tmplhs, rhs));
process_constraint (new_constraint (lhs, tmplhs));
}
else if (rhs.type == ADDRESSOF && lhs.type == DEREF)
else if ((rhs.type != SCALAR || rhs.offset != 0) && lhs.type == DEREF)
{
/* Split into tmp = &rhs, *lhs = tmp */
struct constraint_expr tmplhs;
@ -3747,7 +3747,7 @@ make_transitive_closure_constraints (varinfo_t vi)
{
struct constraint_expr lhs, rhs;
/* VAR = *VAR; */
/* VAR = *(VAR + UNKNOWN); */
lhs.type = SCALAR;
lhs.var = vi->id;
lhs.offset = 0;
@ -3757,6 +3757,23 @@ make_transitive_closure_constraints (varinfo_t vi)
process_constraint (new_constraint (lhs, rhs));
}
/* Add constraints to that the solution of VI has all subvariables added. */
static void
make_any_offset_constraints (varinfo_t vi)
{
struct constraint_expr lhs, rhs;
/* VAR = VAR + UNKNOWN; */
lhs.type = SCALAR;
lhs.var = vi->id;
lhs.offset = 0;
rhs.type = SCALAR;
rhs.var = vi->id;
rhs.offset = UNKNOWN_OFFSET;
process_constraint (new_constraint (lhs, rhs));
}
/* Temporary storage for fake var decls. */
struct obstack fake_var_decl_obstack;
@ -3902,15 +3919,12 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
&& (flags & EAF_NOESCAPE))
{
varinfo_t uses = get_call_use_vi (stmt);
varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
make_constraint_to (tem->id, arg);
make_any_offset_constraints (tem);
if (!(flags & EAF_DIRECT))
{
varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
make_constraint_to (tem->id, arg);
make_transitive_closure_constraints (tem);
make_copy_constraint (uses, tem->id);
}
else
make_constraint_to (uses->id, arg);
make_transitive_closure_constraints (tem);
make_copy_constraint (uses, tem->id);
returns_uses = true;
}
else if (flags & EAF_NOESCAPE)
@ -3920,6 +3934,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
varinfo_t clobbers = get_call_clobber_vi (stmt);
varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
make_constraint_to (tem->id, arg);
make_any_offset_constraints (tem);
if (!(flags & EAF_DIRECT))
make_transitive_closure_constraints (tem);
make_copy_constraint (uses, tem->id);
@ -3945,7 +3960,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
if (returns_uses)
{
rhsc.var = get_call_use_vi (stmt)->id;
rhsc.offset = 0;
rhsc.offset = UNKNOWN_OFFSET;
rhsc.type = SCALAR;
results->safe_push (rhsc);
}
@ -4054,6 +4069,7 @@ handle_const_call (gcall *stmt, vec<ce_s> *results)
if (gimple_call_chain (stmt))
{
varinfo_t uses = get_call_use_vi (stmt);
make_any_offset_constraints (uses);
make_transitive_closure_constraints (uses);
make_constraint_to (uses->id, gimple_call_chain (stmt));
rhsc.var = uses->id;
@ -4062,16 +4078,24 @@ handle_const_call (gcall *stmt, vec<ce_s> *results)
results->safe_push (rhsc);
}
/* May return arguments. */
/* May return offsetted arguments. */
varinfo_t tem = NULL;
if (gimple_call_num_args (stmt) != 0)
tem = new_var_info (NULL_TREE, "callarg", true);
for (k = 0; k < gimple_call_num_args (stmt); ++k)
{
tree arg = gimple_call_arg (stmt, k);
auto_vec<ce_s> argc;
unsigned i;
struct constraint_expr *argp;
get_constraint_for_rhs (arg, &argc);
FOR_EACH_VEC_ELT (argc, i, argp)
results->safe_push (*argp);
make_constraints_to (tem->id, argc);
}
if (tem)
{
ce_s ce;
ce.type = SCALAR;
ce.var = tem->id;
ce.offset = UNKNOWN_OFFSET;
results->safe_push (ce);
}
/* May return addresses of globals. */
@ -4098,6 +4122,7 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
if (!uses)
{
uses = get_call_use_vi (stmt);
make_any_offset_constraints (uses);
make_transitive_closure_constraints (uses);
}
make_constraint_to (uses->id, arg);
@ -4109,6 +4134,7 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
if (!uses)
{
uses = get_call_use_vi (stmt);
make_any_offset_constraints (uses);
make_transitive_closure_constraints (uses);
}
make_constraint_to (uses->id, gimple_call_chain (stmt));