This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 2/2] Replace the modified flag with AA-queries
- From: Martin Jambor <mjambor at suse dot cz>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Guenther <rguenther at suse dot de>, Jan Hubicka <hubicka at ucw dot cz>
- Date: Mon, 21 Jun 2010 11:54:22 +0200
- Subject: [PATCH 2/2] Replace the modified flag with AA-queries
- References: <20100621095420.256789766@virgil.suse.cz>
Hi,
indirect inlining was written before we had AA-info at our disposal in
the "early" passes and so when confronted with the necessity to
guarantee that a member pointer parameter was not changed before it
was used I have resorted to requiring it is never modified in the
whole function.
With alias analysis information this is no longer necessary. This
code therefore does away with the flag and uses AA instead. To big
extent I have copied the clobbering identification code from IPA-SRA
and hope I got it correct.
I added a new testcase checking that we so not indirect-inline when we
shouldn't because a member-pointer parameter is modified before being
passed on.
I am aware that there are no hunks removing testcase
gcc.dg/ipa/modif-1.c in the patch, that is because I generate my
patches with quilt rather than svn. I will remember to svn-delete the
file.
I have bootstrapped and tested this patch (on top of the previous one)
on x86_64-linux without any issues, OK for trunk?
Thanks,
Martin
2010-06-18 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h (struct ipa_param_descriptor): Remove the modified flag.
(ipa_is_param_modified): Removed.
* ipa-prop.c (visit_store_addr_for_mod_analysis): Do not set the
modified flag.
(mark_modified): New function.
(is_parm_modified_at_call): Likewise.
(compute_pass_through_member_ptrs): Use is_parm_modified_at_call
instead of ipa_is_param_modified.
(ipa_analyze_indirect_call_uses): Likewise.
(ipa_print_node_params): Do not dump the modified flag.
(ipa_write_node_info): Do not stream the modified flag.
(ipa_read_node_info): Likewise.
* testsuite/g++.dg/ipa/iinline-2.C: New test.
* testsuite/gcc.dg/ipa/modif-1.c: Removed.
Index: icln/gcc/ipa-prop.c
===================================================================
--- icln.orig/gcc/ipa-prop.c 2010-06-20 18:23:13.000000000 +0200
+++ icln/gcc/ipa-prop.c 2010-06-20 18:24:32.000000000 +0200
@@ -212,7 +212,6 @@ visit_store_addr_for_mod_analysis (gimpl
{
int index = ipa_get_param_decl_index (info, op);
gcc_assert (index >= 0);
- info->params[index].modified = true;
info->params[index].used = true;
}
@@ -707,6 +706,34 @@ type_like_member_ptr_p (tree type, tree
return true;
}
+/* Callback of walk_aliased_vdefs. Flags that it has been invoked to the
+ boolean variable pointed to by DATA. */
+
+static bool
+mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
+ void *data)
+{
+ bool *b = (bool *) data;
+ *b = true;
+ return true;
+}
+
+/* Return true if the formal parameter PARM might have been modified in this
+ function before reaching the statement CALL. */
+
+static bool
+is_parm_modified_at_call (gimple call, tree parm)
+{
+ bool modified = false;
+ ao_ref refd;
+
+ ao_ref_init (&refd, parm);
+ walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
+ &modified, NULL);
+
+ return modified;
+}
+
/* Go through arguments of the CALL and for every one that looks like a member
pointer, check whether it can be safely declared pass-through and if so,
mark that to the corresponding item of jump FUNCTIONS. Return true iff
@@ -733,7 +760,7 @@ compute_pass_through_member_ptrs (struct
int index = ipa_get_param_decl_index (info, arg);
gcc_assert (index >=0);
- if (!ipa_is_param_modified (info, index))
+ if (!is_parm_modified_at_call (call, arg))
{
functions[num].type = IPA_JF_PASS_THROUGH;
functions[num].value.pass_through.formal_id = index;
@@ -1184,7 +1211,7 @@ ipa_analyze_indirect_call_uses (struct c
return;
index = ipa_get_param_decl_index (info, rec);
- if (index >= 0 && !ipa_is_param_modified (info, index))
+ if (index >= 0 && !is_parm_modified_at_call (call, rec))
ipa_note_param_call (node, index, call, false);
return;
@@ -1854,8 +1881,6 @@ ipa_print_node_params (FILE * f, struct
(DECL_NAME (temp)
? (*lang_hooks.decl_printable_name) (temp, 2)
: "(unnamed)"));
- if (ipa_is_param_modified (info, i))
- fprintf (f, " modified");
if (ipa_is_param_used (info, i))
fprintf (f, " used");
fprintf (f, "\n");
@@ -2470,10 +2495,7 @@ ipa_write_node_info (struct output_block
gcc_assert (!info->node_enqueued);
gcc_assert (!info->ipcp_orig_node);
for (j = 0; j < ipa_get_param_count (info); j++)
- {
- bp_pack_value (&bp, info->params[j].modified, 1);
- bp_pack_value (&bp, info->params[j].used, 1);
- }
+ bp_pack_value (&bp, info->params[j].used, 1);
lto_output_bitpack (&bp);
for (e = node->callees; e; e = e->next_callee)
{
@@ -2511,10 +2533,7 @@ ipa_read_node_info (struct lto_input_blo
}
info->node_enqueued = false;
for (k = 0; k < ipa_get_param_count (info); k++)
- {
- info->params[k].modified = bp_unpack_value (&bp, 1);
- info->params[k].used = bp_unpack_value (&bp, 1);
- }
+ info->params[k].used = bp_unpack_value (&bp, 1);
for (e = node->callees; e; e = e->next_callee)
{
struct ipa_edge_args *args = IPA_EDGE_REF (e);
Index: icln/gcc/ipa-prop.h
===================================================================
--- icln.orig/gcc/ipa-prop.h 2010-06-20 17:56:03.000000000 +0200
+++ icln/gcc/ipa-prop.h 2010-06-20 18:23:16.000000000 +0200
@@ -161,8 +161,6 @@ struct ipa_param_descriptor
struct ipcp_lattice ipcp_lattice;
/* PARAM_DECL of this parameter. */
tree decl;
- /* Whether the value parameter has been modified within the function. */
- unsigned modified : 1;
/* The parameter is used. */
unsigned used : 1;
};
@@ -228,17 +226,6 @@ ipa_get_param (struct ipa_node_params *i
return info->params[i].decl;
}
-/* Return the modification flag corresponding to the Ith formal parameter of
- the function associated with INFO. Note that there is no setter method as
- the goal is to set all flags when building the array in
- ipa_detect_param_modifications. */
-
-static inline bool
-ipa_is_param_modified (struct ipa_node_params *info, int i)
-{
- return info->params[i].modified;
-}
-
/* Return the used flag corresponding to the Ith formal parameter of
the function associated with INFO. */
Index: icln/gcc/testsuite/g++.dg/ipa/iinline-2.C
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ icln/gcc/testsuite/g++.dg/ipa/iinline-2.C 2010-06-20 18:23:16.000000000 +0200
@@ -0,0 +1,64 @@
+/* Verify that we do not indirect-inline using member pointer
+ parameters which have been modified. */
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-early-inlining" } */
+/* { dg-add-options bind_pic_locally } */
+
+extern "C" void abort (void);
+
+class String
+{
+private:
+ const char *data;
+
+public:
+ String (const char *d) : data(d)
+ {}
+
+ int funcOne (int stuff) const;
+ int funcTwo (int stuff) const;
+};
+
+
+int String::funcOne (int stuff) const
+{
+ return stuff + 1;
+}
+
+int String::funcTwo (int stuff) const
+{
+ return stuff + 100;
+}
+
+int (String::* gmp)(int stuff) const = &String::funcTwo;
+
+int docalling_1 (int (String::* f)(int stuff) const)
+{
+ String S ("muhehehe");
+
+ return (S.*f)(4);
+}
+
+int docalling (int a, int (String::* f)(int stuff) const)
+{
+ if (a < 200)
+ f = gmp;
+
+ return docalling_1 (f);
+}
+
+int __attribute__ ((noinline,noclone)) get_input (void)
+{
+ return 1;
+}
+
+int main (int argc, char *argv[])
+{
+ int i = 0;
+ while (i < 10)
+ i += docalling (get_input (), &String::funcOne);
+
+ if (i != 104)
+ abort();
+ return 0;
+}