Commit 91bb9f80 by Martin Jambor Committed by Martin Jambor

Indirect inlining of targets from references of global constants

2016-05-18  Martin Jambor  <mjambor@suse.cz>

	PR ipa/69708
	* cgraph.h (cgraph_indirect_call_info): New field
	guaranteed_unmodified.
	* ipa-cp.c (ipa_get_indirect_edge_target_1): Also pass parameter value
	to ipa_find_agg_cst_for_param, check guaranteed_unmodified when
	appropriate.
	* ipa-inline-analysis.c (evaluate_conditions_for_known_args): Also
	pass the parameter value to ipa_find_agg_cst_for_param.
	* ipa-prop.c (ipa_load_from_parm_agg): New parameter
	guaranteed_unmodified, store AA results there instead of bailing out
	if present.
	(ipa_note_param_call): Also initialize guaranteed_unmodified flag.
	(ipa_analyze_indirect_call_uses): Also set guaranteed_unmodified flag.
	(find_constructor_constant_at_offset): New function.
	(ipa_find_agg_cst_from_init): Likewise.
	(ipa_find_agg_cst_for_param): Also seearch for aggregate values in
	static initializers of contants, report back through a new paameter
	from_global_constant if that was the case.
	(try_make_edge_direct_simple_call): Also pass parameter value to
	ipa_find_agg_cst_for_param, check guaranteed_unmodified when
	appropriate.
	(ipa_write_indirect_edge_info): Stream new flag guaranteed_unmodified.
	(ipa_read_indirect_edge_info): Likewise.
	* ipa-prop.h (ipa_find_agg_cst_for_param): Update declaration.
	(ipa_load_from_parm_agg): Likewise.

testsuite/
	* gcc.dg/ipa/iinline-cstagg-1.c: New test.
	* gcc.dg/ipa/ipcp-cstagg-1.c: Likewise.
	* gcc.dg/ipa/ipcp-cstagg-2.c: Likewise.
	* gcc.dg/ipa/ipcp-cstagg-3.c: Likewise.
	* gcc.dg/ipa/ipcp-cstagg-4.c: Likewise.

From-SVN: r236416
parent c584aca6
2016-05-18 Martin Jambor <mjambor@suse.cz>
PR ipa/69708
* cgraph.h (cgraph_indirect_call_info): New field
guaranteed_unmodified.
* ipa-cp.c (ipa_get_indirect_edge_target_1): Also pass parameter value
to ipa_find_agg_cst_for_param, check guaranteed_unmodified when
appropriate.
* ipa-inline-analysis.c (evaluate_conditions_for_known_args): Also
pass the parameter value to ipa_find_agg_cst_for_param.
* ipa-prop.c (ipa_load_from_parm_agg): New parameter
guaranteed_unmodified, store AA results there instead of bailing out
if present.
(ipa_note_param_call): Also initialize guaranteed_unmodified flag.
(ipa_analyze_indirect_call_uses): Also set guaranteed_unmodified flag.
(find_constructor_constant_at_offset): New function.
(ipa_find_agg_cst_from_init): Likewise.
(ipa_find_agg_cst_for_param): Also seearch for aggregate values in
static initializers of contants, report back through a new paameter
from_global_constant if that was the case.
(try_make_edge_direct_simple_call): Also pass parameter value to
ipa_find_agg_cst_for_param, check guaranteed_unmodified when
appropriate.
(ipa_write_indirect_edge_info): Stream new flag guaranteed_unmodified.
(ipa_read_indirect_edge_info): Likewise.
* ipa-prop.h (ipa_find_agg_cst_for_param): Update declaration.
(ipa_load_from_parm_agg): Likewise.
2016-05-18 Jiong Wang <jiong.wang@arm.com>
PR rtl-optimization/71150
......
......@@ -1579,9 +1579,14 @@ struct GTY(()) cgraph_indirect_call_info
unsigned agg_contents : 1;
/* Set when this is a call through a member pointer. */
unsigned member_ptr : 1;
/* When the previous bit is set, this one determines whether the destination
is loaded from a parameter passed by reference. */
/* When the agg_contents bit is set, this one determines whether the
destination is loaded from a parameter passed by reference. */
unsigned by_ref : 1;
/* When the agg_contents bit is set, this one determines whether we can
deduce from the function body that the loaded value from the reference is
never modified between the invocation of the function and the load
point. */
unsigned guaranteed_unmodified : 1;
/* For polymorphic calls this specify whether the virtual table pointer
may have changed in between function entry and the call. */
unsigned vptr_changed : 1;
......
......@@ -1999,9 +1999,9 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
if (ie->indirect_info->agg_contents)
{
if (agg_reps)
t = NULL;
if (agg_reps && ie->indirect_info->guaranteed_unmodified)
{
t = NULL;
while (agg_reps)
{
if (agg_reps->index == param_index
......@@ -2014,15 +2014,22 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
agg_reps = agg_reps->next;
}
}
else if (known_aggs.length () > (unsigned int) param_index)
if (!t)
{
struct ipa_agg_jump_function *agg;
agg = known_aggs[param_index];
t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
ie->indirect_info->by_ref);
if (known_aggs.length () > (unsigned int) param_index)
agg = known_aggs[param_index];
else
agg = NULL;
bool from_global_constant;
t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
ie->indirect_info->offset,
ie->indirect_info->by_ref,
&from_global_constant);
if (!from_global_constant
&& !ie->indirect_info->guaranteed_unmodified)
t = NULL_TREE;
}
else
t = NULL;
}
else
t = known_csts[param_index];
......@@ -2066,7 +2073,8 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
{
struct ipa_agg_jump_function *agg;
agg = known_aggs[param_index];
t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset,
t = ipa_find_agg_cst_for_param (agg, known_csts[param_index],
ie->indirect_info->offset,
true);
}
......
......@@ -853,7 +853,8 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
if (known_aggs.exists ())
{
agg = known_aggs[c->operand_num];
val = ipa_find_agg_cst_for_param (agg, c->offset, c->by_ref);
val = ipa_find_agg_cst_for_param (agg, known_vals[c->operand_num],
c->offset, c->by_ref);
}
else
val = NULL_TREE;
......
......@@ -636,11 +636,14 @@ tree ipa_impossible_devirt_target (struct cgraph_edge *, tree);
void ipa_analyze_node (struct cgraph_node *);
/* Aggregate jump function related functions. */
tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *, HOST_WIDE_INT,
bool);
bool ipa_load_from_parm_agg (struct ipa_func_body_info *,
vec<ipa_param_descriptor>, gimple *, tree, int *,
HOST_WIDE_INT *, HOST_WIDE_INT *, bool *);
tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg, tree scalar,
HOST_WIDE_INT offset, bool by_ref,
bool *from_global_constant = NULL);
bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
vec<ipa_param_descriptor> descriptors,
gimple *stmt, tree op, int *index_p,
HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p,
bool *by_ref, bool *guaranteed_unmodified = NULL);
/* Debugging interface. */
void ipa_print_node_params (FILE *, struct cgraph_node *node);
......
2016-05-18 Martin Jambor <mjambor@suse.cz>
PR ipa/69708
* gcc.dg/ipa/iinline-cstagg-1.c: New test.
* gcc.dg/ipa/ipcp-cstagg-1.c: Likewise.
* gcc.dg/ipa/ipcp-cstagg-2.c: Likewise.
* gcc.dg/ipa/ipcp-cstagg-3.c: Likewise.
* gcc.dg/ipa/ipcp-cstagg-4.c: Likewise.
2016-05-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/69793
......
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-ipa-inline-details -fno-early-inlining -fno-ipa-sra -fno-ipa-cp" } */
typedef struct S
{
int add_offset;
int (*call)(int);
} S;
static int
bar (const S *f, int x)
{
x = f->call(x);
return x;
}
static int
thisisthetarget (int x)
{
return x * x;
}
static const S s = {16, thisisthetarget};
int
outerfunction (int x)
{
return bar (&s, x);
}
int
obfuscate (int x)
{
return bar ((S *) 0, x);
}
/* { dg-final { scan-ipa-dump "thisisthetarget\[^\\n\]*inline copy in outerfunction" "inline" } } */
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-ipa-cp-details" } */
typedef struct S
{
int add_offset;
int (*call)(int);
} S;
extern const S *gs;
static int __attribute__((noinline))
bar (const S *f, int x)
{
x = f->call(x);
x = f->call(x);
x = f->call(x);
gs = f;
return x;
}
static int
sq (int x)
{
return x * x;
}
static const S s = {16, sq};
int
g (int x)
{
return bar (&s, x);
}
int
obfuscate (int x)
{
return bar ((S *) 0, x);
}
/* { dg-final { scan-ipa-dump-times "Discovered an indirect call to a known target" 3 "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-ipa-cp-details" } */
typedef struct S
{
int (*call)(int);
} S;
static int __attribute__((noinline))
bar (const S *f, int x)
{
x = f->call(x);
return x;
}
extern void impossible_aa (void);
static int __attribute__((noinline))
baz (const S *f, int x)
{
impossible_aa ();
return bar (f, x);
}
static int
sq (int x)
{
return x * x;
}
static const S s = {sq};
int
g (int x)
{
return baz (&s, x);
}
int
obfuscate (int x)
{
return baz ((S *) 0, x);
}
/* { dg-final { scan-ipa-dump "Discovered an indirect call to a known target" "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-ipa-cp-details" } */
#define N 4
typedef int (* const A[N])(int);
extern const A *ga;
static int __attribute__((noinline))
bar (const A *f, int x)
{
x = (*f)[2](x);
x = (*f)[2](x);
x = (*f)[2](x);
ga = f;
return x;
}
static int
zero (int x)
{
return 0;
}
static int
addone (int x)
{
return x + 1;
}
static int
sq (int x)
{
return x * x;
}
static int
cube (int x)
{
return x * x * x;
}
static const A a = {zero, addone, sq, cube};
int
g (int x)
{
return bar (&a, x);
}
int
obfuscate (int x)
{
return bar ((A *) 0, x);
}
/* { dg-final { scan-ipa-dump-times "Discovered an indirect call to a known target" 3 "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-ipa-cp-details" } */
#define N 4
typedef int (* const A[N])(int);
typedef struct S
{
int add_offset;
A a;
} S;
extern const S *gs;
static int __attribute__((noinline))
bar (const S *f, int x)
{
gs = f;
x = f->a[2](x);
x = f->a[2](x);
x = f->a[2](x);
return x;
}
static int
zero (int x)
{
return 0;
}
static int
addone (int x)
{
return x + 1;
}
static int
sq (int x)
{
return x * x;
}
static int
cube (int x)
{
return x * x * x;
}
static const S s = {64, {zero, addone, sq, cube}};
int
g (int x)
{
return bar (&s, x);
}
int
obfuscate (int x)
{
return bar ((S *) 0, x);
}
/* { dg-final { scan-ipa-dump-times "Discovered an indirect call to a known target" 3 "cp" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment