re PR ipa/70760 (wrong generated code for std::make_unique with -fipa-pta)

2016-04-27  Richard Biener  <rguenther@suse.de>

	PR ipa/70760
	* tree-ssa-structalias.c (find_func_aliases_for_call): Use
	aggregate_value_p to determine if a function result is
	returned by reference.
	(ipa_pta_execute): Functions having their address taken are
	not automatically nonlocal.

	* g++.dg/ipa/ipa-pta-2.C: New testcase.
	* gcc.dg/ipa/ipa-pta-1.c: Adjust.

From-SVN: r235511
This commit is contained in:
Richard Biener 2016-04-27 14:10:04 +00:00 committed by Richard Biener
parent b3b2bae4e2
commit 72ed2b9c76
5 changed files with 71 additions and 43 deletions

View File

@ -1,3 +1,12 @@
2016-04-27 Richard Biener <rguenther@suse.de>
PR ipa/70760
* tree-ssa-structalias.c (find_func_aliases_for_call): Use
aggregate_value_p to determine if a function result is
returned by reference.
(ipa_pta_execute): Functions having their address taken are
not automatically nonlocal.
2016-04-27 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/70683

View File

@ -1,3 +1,9 @@
2016-04-27 Richard Biener <rguenther@suse.de>
PR ipa/70760
* g++.dg/ipa/ipa-pta-2.C: New testcase.
* gcc.dg/ipa/ipa-pta-1.c: Adjust.
2016-04-27 Nathan Sidwell <nathan@acm.org>
* g++.dg/cpp0x/constexpr-recursion3.C: New.

View File

@ -0,0 +1,37 @@
// { dg-do run }
// { dg-options "-O2 -fipa-pta" }
extern "C" void abort (void);
struct Y { ~Y(); int i; };
Y::~Y () {}
static Y __attribute__((noinline)) foo ()
{
Y res;
res.i = 3;
return res;
}
static Y __attribute__((noinline)) bar ()
{
Y res;
res.i = 42;
return res;
}
static Y (*fn) ();
int a;
int main()
{
if (a)
fn = foo;
else
fn = bar;
Y res = fn ();
if (res.i != 42)
abort ();
return 0;
}

View File

@ -40,13 +40,10 @@ int main()
}
/* IPA PTA needs to handle indirect calls properly. Verify that
both bar and foo get a (and only a) in their arguments points-to sets.
??? As bar and foo have their address taken there might be callers
not seen by IPA PTA (if the address escapes the unit which we only compute
during IPA PTA...). Thus the solution also includes NONLOCAL. */
both bar and foo get a (and only a) in their arguments points-to sets. */
/* { dg-final { scan-ipa-dump "fn_1 = { bar foo }" "pta2" } } */
/* { dg-final { scan-ipa-dump "bar.arg0 = { NONLOCAL a }" "pta2" } } */
/* { dg-final { scan-ipa-dump "bar.arg1 = { NONLOCAL a }" "pta2" } } */
/* { dg-final { scan-ipa-dump "foo.arg0 = { NONLOCAL a }" "pta2" } } */
/* { dg-final { scan-ipa-dump "foo.arg1 = { NONLOCAL a }" "pta2" } } */
/* { dg-final { scan-ipa-dump "bar.arg0 = { a }" "pta2" } } */
/* { dg-final { scan-ipa-dump "bar.arg1 = { a }" "pta2" } } */
/* { dg-final { scan-ipa-dump "foo.arg0 = { a }" "pta2" } } */
/* { dg-final { scan-ipa-dump "foo.arg1 = { a }" "pta2" } } */

View File

@ -4641,12 +4641,11 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
auto_vec<ce_s, 2> lhsc;
struct constraint_expr rhs;
struct constraint_expr *lhsp;
bool aggr_p = aggregate_value_p (lhsop, gimple_call_fntype (t));
get_constraint_for (lhsop, &lhsc);
rhs = get_function_part_constraint (fi, fi_result);
if (fndecl
&& DECL_RESULT (fndecl)
&& DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
if (aggr_p)
{
auto_vec<ce_s, 2> tem;
tem.quick_push (rhs);
@ -4656,22 +4655,19 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
}
FOR_EACH_VEC_ELT (lhsc, j, lhsp)
process_constraint (new_constraint (*lhsp, rhs));
}
/* If we pass the result decl by reference, honor that. */
if (lhsop
&& fndecl
&& DECL_RESULT (fndecl)
&& DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
{
struct constraint_expr lhs;
struct constraint_expr *rhsp;
/* If we pass the result decl by reference, honor that. */
if (aggr_p)
{
struct constraint_expr lhs;
struct constraint_expr *rhsp;
get_constraint_for_address_of (lhsop, &rhsc);
lhs = get_function_part_constraint (fi, fi_result);
FOR_EACH_VEC_ELT (rhsc, j, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
rhsc.truncate (0);
get_constraint_for_address_of (lhsop, &rhsc);
lhs = get_function_part_constraint (fi, fi_result);
FOR_EACH_VEC_ELT (rhsc, j, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
rhsc.truncate (0);
}
}
/* If we use a static chain, pass it along. */
@ -7686,30 +7682,13 @@ ipa_pta_execute (void)
gcc_assert (!node->clone_of);
/* When parallelizing a code region, we split the region off into a
separate function, to be run by several threads in parallel. So for a
function foo, we split off a region into a function
foo._0 (void *foodata), and replace the region with some variant of a
function call run_on_threads (&foo._0, data). The '&foo._0' sets the
address_taken bit for function foo._0, which would make it non-local.
But for the purpose of ipa-pta, we can regard the run_on_threads call
as a local call foo._0 (data), so we ignore address_taken on nodes
with parallelized_function set.
Note: this is only safe, if foo and foo._0 are in the same lto
partition. */
bool node_address_taken = ((node->parallelized_function
&& !node->used_from_other_partition)
? false
: node->address_taken);
/* For externally visible or attribute used annotated functions use
local constraints for their arguments.
For local functions we see all callers and thus do not need initial
constraints for parameters. */
bool nonlocal_p = (node->used_from_other_partition
|| node->externally_visible
|| node->force_output
|| node_address_taken);
|| node->force_output);
node->call_for_symbol_thunks_and_aliases (refered_from_nonlocal_fn,
&nonlocal_p, true);