Commit 4502fe8d by Martin Jambor Committed by Martin Jambor

re PR middle-end/42371 (dead code not eliminated during folding with whole-program)

2013-05-13  Martin Jambor  <mjambor@suse.cz>

	PR middle-end/42371
	* ipa-prop.h (IPA_UNDESCRIBED_USE): New macro.
	(ipa_constant_data): New type.
	(ipa_jump_func): Use ipa_constant_data to hold information about
	constant jump functions.
	(ipa_get_jf_constant): Adjust to jump function type changes.
	(ipa_get_jf_constant_rdesc): New function.
	(ipa_param_descriptor): New field controlled_uses.
	(ipa_get_controlled_uses): New function.
	(ipa_set_controlled_uses): Likewise.
	* ipa-ref.h (ipa_find_reference): Declare.
	* ipa-prop.c (ipa_cst_ref_desc): New type.
	(ipa_print_node_jump_functions_for_edge): Adjust for jump function type
	changes.
	(ipa_set_jf_constant): Likewise.  Also create reference descriptions.
	New parameter cs.  Adjust all callers.
	(ipa_analyze_params_uses): Detect uncontrolled and controlled uses.
	(remove_described_reference): New function.
	(jfunc_rdesc_usable): Likewise.
	(try_make_edge_direct_simple_call): Decrement controlled use count,
	attempt to remove reference if it hits zero.
	(combine_controlled_uses_counters): New function.
	(propagate_controlled_uses): Likewise.
	(ipa_propagate_indirect_call_infos): Call propagate_controlled_uses.
	(ipa_edge_duplication_hook): Duplicate reference descriptions.
	(ipa_print_node_params): Print described use counter.
	(ipa_write_jump_function): Adjust to jump function type changes.
	(ipa_read_jump_function): New parameter CS, pass it to
	ipa_set_jf_constant.  Adjust caller.
	(ipa_write_node_info): Stream controlled use count
	(ipa_read_node_info): Likewise.
	* cgraph.c (cgraph_mark_address_taken_node): Bail out instead of
	asserting.
	* ipa-cp.c (ipcp_discover_new_direct_edges): Decrement controlled use
	count.  Remove cloning-added reference if it reaches zero.
	* ipa-ref.c (ipa_find_reference): New function.

testsuite/
	* gcc.dg/ipa/remref-0.c: New test.
	* gcc.dg/ipa/remref-1a.c: Likewise.
	* gcc.dg/ipa/remref-1b.c: Likewise.
	* gcc.dg/ipa/remref-2a.c: Likewise.
	* gcc.dg/ipa/remref-2b.c: Likewise.

From-SVN: r198821
parent 0864bfc2
2013-05-13 Martin Jambor <mjambor@suse.cz>
PR middle-end/42371
* ipa-prop.h (IPA_UNDESCRIBED_USE): New macro.
(ipa_constant_data): New type.
(ipa_jump_func): Use ipa_constant_data to hold information about
constant jump functions.
(ipa_get_jf_constant): Adjust to jump function type changes.
(ipa_get_jf_constant_rdesc): New function.
(ipa_param_descriptor): New field controlled_uses.
(ipa_get_controlled_uses): New function.
(ipa_set_controlled_uses): Likewise.
* ipa-ref.h (ipa_find_reference): Declare.
* ipa-prop.c (ipa_cst_ref_desc): New type.
(ipa_print_node_jump_functions_for_edge): Adjust for jump function type
changes.
(ipa_set_jf_constant): Likewise. Also create reference descriptions.
New parameter cs. Adjust all callers.
(ipa_analyze_params_uses): Detect uncontrolled and controlled uses.
(remove_described_reference): New function.
(jfunc_rdesc_usable): Likewise.
(try_make_edge_direct_simple_call): Decrement controlled use count,
attempt to remove reference if it hits zero.
(combine_controlled_uses_counters): New function.
(propagate_controlled_uses): Likewise.
(ipa_propagate_indirect_call_infos): Call propagate_controlled_uses.
(ipa_edge_duplication_hook): Duplicate reference descriptions.
(ipa_print_node_params): Print described use counter.
(ipa_write_jump_function): Adjust to jump function type changes.
(ipa_read_jump_function): New parameter CS, pass it to
ipa_set_jf_constant. Adjust caller.
(ipa_write_node_info): Stream controlled use count
(ipa_read_node_info): Likewise.
* cgraph.c (cgraph_mark_address_taken_node): Bail out instead of
asserting.
* ipa-cp.c (ipcp_discover_new_direct_edges): Decrement controlled use
count. Remove cloning-added reference if it reaches zero.
* ipa-ref.c (ipa_find_reference): New function.
2013-05-13 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
* config/i386/i386.c (processor_target_table): Modified default
......
......@@ -1409,7 +1409,14 @@ cgraph_remove_node (struct cgraph_node *node)
void
cgraph_mark_address_taken_node (struct cgraph_node *node)
{
gcc_assert (!node->global.inlined_to);
/* Indirect inlining can figure out that all uses of the address are
inlined. */
if (node->global.inlined_to)
{
gcc_assert (cfun->after_inlining);
gcc_assert (node->callers->indirect_inlining_edge);
return;
}
/* FIXME: address_taken flag is used both as a shortcut for testing whether
IPA_REF_ADDR reference exists (and thus it should be set on node
representing alias we take address of) and as a test whether address
......
......@@ -2276,8 +2276,36 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
aggvals);
if (target)
{
ipa_make_edge_direct_to_target (ie, target);
struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target);
found = true;
if (cs && !ie->indirect_info->agg_contents
&& !ie->indirect_info->polymorphic)
{
struct ipa_node_params *info = IPA_NODE_REF (node);
int param_index = ie->indirect_info->param_index;
int c = ipa_get_controlled_uses (info, param_index);
if (c != IPA_UNDESCRIBED_USE)
{
struct ipa_ref *to_del;
c--;
ipa_set_controlled_uses (info, param_index, c);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " controlled uses count of param "
"%i bumped down to %i\n", param_index, c);
if (c == 0
&& (to_del = ipa_find_reference ((symtab_node) node,
(symtab_node) cs->callee,
NULL)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " and even removing its "
"cloning-created reference\n");
ipa_remove_reference (to_del);
}
}
}
}
}
/* Turning calls to direct calls will improve overall summary. */
......
......@@ -29,6 +29,8 @@ along with GCC; see the file COPYING3. If not see
/* The following definitions and interfaces are used by
interprocedural analyses or parameters. */
#define IPA_UNDESCRIBED_USE -1
/* ipa-prop.c stuff (ipa-cp, indirect inlining): */
/* A jump function for a callsite represents the values passed as actual
......@@ -84,6 +86,17 @@ struct GTY(()) ipa_known_type_data
tree component_type;
};
struct ipa_cst_ref_desc;
/* Structure holding data required to describe a constant jump function. */
struct GTY(()) ipa_constant_data
{
/* THe value of the constant. */
tree value;
/* Pointer to the structure that describes the reference. */
struct ipa_cst_ref_desc GTY((skip)) *rdesc;
};
/* Structure holding data required to describe a pass-through jump function. */
struct GTY(()) ipa_pass_through_data
......@@ -172,7 +185,7 @@ typedef struct GTY (()) ipa_jump_func
union jump_func_value
{
struct ipa_known_type_data GTY ((tag ("IPA_JF_KNOWN_TYPE"))) known_type;
tree GTY ((tag ("IPA_JF_CONST"))) constant;
struct ipa_constant_data GTY ((tag ("IPA_JF_CONST"))) constant;
struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) pass_through;
struct ipa_ancestor_jf_data GTY ((tag ("IPA_JF_ANCESTOR"))) ancestor;
} GTY ((desc ("%1.type"))) value;
......@@ -213,7 +226,14 @@ static inline tree
ipa_get_jf_constant (struct ipa_jump_func *jfunc)
{
gcc_checking_assert (jfunc->type == IPA_JF_CONST);
return jfunc->value.constant;
return jfunc->value.constant.value;
}
static inline struct ipa_cst_ref_desc *
ipa_get_jf_constant_rdesc (struct ipa_jump_func *jfunc)
{
gcc_checking_assert (jfunc->type == IPA_JF_CONST);
return jfunc->value.constant.rdesc;
}
/* Return the operand of a pass through jmp function JFUNC. */
......@@ -296,6 +316,10 @@ struct ipa_param_descriptor
{
/* PARAM_DECL of this parameter. */
tree decl;
/* If all uses of the parameter are described by ipa-prop structures, this
says how many there are. If any use could not be described by means of
ipa-prop structures, this is IPA_UNDESCRIBED_USE. */
int controlled_uses;
/* The parameter is used. */
unsigned used : 1;
};
......@@ -365,6 +389,23 @@ ipa_set_param_used (struct ipa_node_params *info, int i, bool val)
info->descriptors[i].used = val;
}
/* Return how many uses described by ipa-prop a parameter has or
IPA_UNDESCRIBED_USE if there is a use that is not described by these
structures. */
static inline int
ipa_get_controlled_uses (struct ipa_node_params *info, int i)
{
return info->descriptors[i].controlled_uses;
}
/* Set the controlled counter of a given parameter. */
static inline void
ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val)
{
info->descriptors[i].controlled_uses = val;
}
/* Return the used flag corresponding to the Ith formal parameter of the
function associated with INFO. */
......
......@@ -198,3 +198,20 @@ ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list)
return true;
return false;
}
/* Find the structure describing a reference in REFERRING_NODE to REFERRED_NODE
and associated with statement STMT. */
struct ipa_ref *
ipa_find_reference (symtab_node referring_node, symtab_node referred_node,
gimple stmt)
{
struct ipa_ref *r = NULL;
int i;
FOR_EACH_VEC_SAFE_ELT (referring_node->symbol.ref_list.references, i, r)
if (r->referred == referred_node
&& (in_lto_p || r->stmt == stmt))
return r;
return NULL;
}
......@@ -71,3 +71,4 @@ void ipa_clone_references (symtab_node, struct ipa_ref_list *);
void ipa_clone_referring (symtab_node, struct ipa_ref_list *);
bool ipa_ref_cannot_lead_to_return (struct ipa_ref *);
bool ipa_ref_has_aliases_p (struct ipa_ref_list *);
struct ipa_ref * ipa_find_reference (symtab_node, symtab_node, gimple);
2013-05-13 Martin Jambor <mjambor@suse.cz>
PR middle-end/42371
* gcc.dg/ipa/remref-0.c: New test.
* gcc.dg/ipa/remref-1a.c: Likewise.
* gcc.dg/ipa/remref-1b.c: Likewise.
* gcc.dg/ipa/remref-2a.c: Likewise.
* gcc.dg/ipa/remref-2b.c: Likewise.
2013-05-13 Marc Glisse <marc.glisse@inria.fr>
* gcc.dg/vector-shift-2.c: New testcase.
......
/* Verify that indirect inlining machinery can remove references to functions
passed as parameters that are never used. */
/* { dg-do compile } */
/* { dg-options "-O3 -fno-early-inlining -fno-ipa-sra -fno-ipa-cp -fdump-ipa-inline -fdump-tree-optimized" } */
extern int __attribute__ ((noinline, noclone, used))
stuff (int i)
{
return 0;
}
static void hooray ()
{
stuff (1);
}
static int hiphip (void (*f)())
{
return stuff (2);
}
int main (void)
{
return hiphip (hooray);
}
/* { dg-final { scan-ipa-dump "ipa-prop: Removed a reference" "inline" } } */
/* { dg-final { scan-tree-dump-not "hooray" "optimized" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that indirect inlining can also remove references of the functions it
discovers calls for. */
/* { dg-do compile } */
/* { dg-options "-O3 -fno-early-inlining -fno-ipa-cp -fdump-ipa-inline -fdump-tree-optimized" } */
int global;
void __attribute__ ((noinline, noclone, used))
stuff (int i)
{
global = i;
}
static void hooray ()
{
stuff (1);
}
static void hiphip (void (*f)())
{
stuff (2);
f ();
}
int main (void)
{
hiphip (hooray);
return 0;
}
/* { dg-final { scan-ipa-dump "ipa-prop: Removed a reference" "inline" } } */
/* { dg-final { scan-tree-dump-not "hooray" "optimized" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that indirect inlining can also remove references of the functions it
discovers calls for, even when nodes being inlined are virtual IPA-CP
clones. */
/* { dg-do compile } */
/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-cp-details -fdump-ipa-inline -fdump-tree-optimized" } */
int global;
void __attribute__ ((noinline, noclone, used))
stuff (int i)
{
global = i;
}
static void hooray ()
{
stuff (1);
}
static void hiphip (void (*f)())
{
stuff (2);
f ();
}
int main (void)
{
hiphip (hooray);
return 0;
}
/* { dg-final { scan-ipa-dump "removing its cloning-created reference" "cp" } } */
/* { dg-final { scan-ipa-dump "ipa-prop: Removed a reference" "inline" } } */
/* { dg-final { scan-tree-dump-not "hooray" "optimized" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that indirect inlining can also remove references of the functions it
discovers calls for. */
/* { dg-do compile } */
/* { dg-options "-O3 -fno-early-inlining -fno-ipa-cp -fdump-ipa-inline -fdump-tree-optimized" } */
int global;
void __attribute__ ((noinline, noclone, used))
stuff (int i)
{
global = i;
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
static void
hooray_1 ()
{
stuff (1);
}
static inline void
hip2_1 (void (*g)())
{
int i;
g ();
/* Some stuff to make the function bigger so that hip1_1 gets inlined
fiorst. */
for (i = 0; i < get_input (); i++)
{
stuff (2);
stuff (2+2);
}
}
static inline void
hip1_1 (void (*g)())
{
hip2_1 (g);
}
static void
hooray_2 ()
{
stuff (1);
}
static inline void
hip2_2 (void (*g)())
{
g ();
}
static inline void
hip1_2 (void (*g)())
{
int i;
hip2_2 (g);
/* Some stuff to make the function bigger so that hip2_2 gets inlined
fiorst. */
for (i = 0; i < get_input (); i++)
{
stuff (2);
stuff (2+2);
}
}
int
main (int argc, int *argv[])
{
int i;
for (i = 0; i < get_input (); i++)
{
hip1_1 (hooray_1);
hip1_2 (hooray_2);
}
return 0;
}
/* { dg-final { scan-ipa-dump-times "ipa-prop: Removed a reference" 2 "inline" } } */
/* { dg-final { scan-tree-dump-not "hooray" "optimized" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that indirect inlining can also remove references of the functions it
discovers calls for, even when nodes being inlined are virtual IPA-CP
clones. */
/* { dg-do compile } */
/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-cp-details -fdump-ipa-inline -fdump-tree-optimized" } */
int global;
void __attribute__ ((noinline, noclone, used))
stuff (int i)
{
global = i;
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
static void
hooray_1 ()
{
stuff (1);
}
static inline void
hip2_1 (void (*g)())
{
int i;
g ();
/* Some stuff to make the function bigger so that hip1_1 gets inlined
fiorst. */
for (i = 0; i < get_input (); i++)
{
stuff (2);
stuff (2+2);
}
}
static inline void
hip1_1 (void (*g)())
{
hip2_1 (g);
}
static void
hooray_2 ()
{
stuff (1);
}
static inline void
hip2_2 (void (*g)())
{
g ();
}
static inline void
hip1_2 (void (*g)())
{
int i;
hip2_2 (g);
/* Some stuff to make the function bigger so that hip2_2 gets inlined
fiorst. */
for (i = 0; i < get_input (); i++)
{
stuff (2);
stuff (2+2);
}
}
int
main (int argc, int *argv[])
{
int i;
for (i = 0; i < get_input (); i++)
{
hip1_1 (hooray_1);
hip1_2 (hooray_2);
}
return 0;
}
/* { dg-final { scan-ipa-dump-times "removing its cloning-created reference" 2 "cp" } } */
/* { dg-final { scan-ipa-dump "ipa-prop: Removed a reference" "inline" } } */
/* { dg-final { scan-ipa-dump-times "ipa-prop: Removing cloning-created reference" 2 "inline" } } */
/* { dg-final { scan-tree-dump-not "hooray" "optimized" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
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