aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2022-03-31 16:50:24 +0200
committerMartin Jambor <mjambor@suse.cz>2022-03-31 16:51:07 +0200
commitf6d65e803623c7ba6c8eb92ce5975fc1b90cd91e (patch)
tree5c505fe4264fc1c244428d915ddcbb45d27c3020
parent90533de067d12159b3fbc847e5397033384f7484 (diff)
downloadgcc-f6d65e803623c7ba6c8eb92ce5975fc1b90cd91e.zip
gcc-f6d65e803623c7ba6c8eb92ce5975fc1b90cd91e.tar.gz
gcc-f6d65e803623c7ba6c8eb92ce5975fc1b90cd91e.tar.bz2
ipa: Create LOAD references when necessary during inlining (PR 103171)
in r12-2523-g13586172d0b70c ipa-prop tracking of jump functions during inlining got the ability to remove ADDR references when inlining discovered that they were not necessary or turn them into LOAD references when we know that what was a function call argument passed by reference will end up as a load (one or more). Unfortunately, the code only creates the LOAD references when replacing removed ADDR references and PR 103171 showed that with some ordering of inlining, we need to add the LOAD reference before we know we can remove the ADDR one - or the reference will be lost, leading to link errors or even ICEs. Specifically in testcase gcc.dg/lto/pr103171_1.c added in this patch, if foo() is inlined to entry(), we need to create the LOAD reference so that when later bar() is inlined into foo() and we discover that the paameter is unused, we can remove the ADDR reference and still keep the varaible around for the load. Martin gcc/ChangeLog: 2022-01-28 Martin Jambor <mjambor@suse.cz> PR ipa/103171 * ipa-prop.cc (propagate_controlled_uses): Add a LOAD reference always when an ADDR_EXPR constant is known to reach a load because of inlining, not just when removing an ADDR reference. gcc/testsuite/ChangeLog: 2022-01-28 Martin Jambor <mjambor@suse.cz> PR ipa/103171 * gcc.dg/ipa/remref-6.c: Adjust dump scan string. * gcc.dg/ipa/remref-7.c: New test. * gcc.dg/lto/pr103171_0.c: New test. * gcc.dg/lto/pr103171_1.c: Likewise.
-rw-r--r--gcc/ipa-prop.cc30
-rw-r--r--gcc/testsuite/gcc.dg/ipa/remref-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/remref-7.c33
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr103171_0.c11
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr103171_1.c35
5 files changed, 96 insertions, 15 deletions
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index e55fe27..72aa3e2 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -4181,6 +4181,20 @@ propagate_controlled_uses (struct cgraph_edge *cs)
int d = ipa_get_controlled_uses (old_root_info, i);
int c = rdesc->refcount;
rdesc->refcount = combine_controlled_uses_counters (c, d);
+ if (rdesc->refcount != IPA_UNDESCRIBED_USE
+ && ipa_get_param_load_dereferenced (old_root_info, i))
+ {
+ tree cst = ipa_get_jf_constant (jf);
+ gcc_checking_assert (TREE_CODE (cst) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (cst, 0))
+ == VAR_DECL));
+ symtab_node *n = symtab_node::get (TREE_OPERAND (cst, 0));
+ new_root->create_reference (n, IPA_REF_LOAD, NULL);
+ if (dump_file)
+ fprintf (dump_file, "ipa-prop: Address IPA constant will reach "
+ "a load so adding LOAD reference from %s to %s.\n",
+ new_root->dump_name (), n->dump_name ());
+ }
if (rdesc->refcount == 0)
{
tree cst = ipa_get_jf_constant (jf);
@@ -4193,20 +4207,8 @@ propagate_controlled_uses (struct cgraph_edge *cs)
symtab_node *n = symtab_node::get (TREE_OPERAND (cst, 0));
if (n)
{
- struct cgraph_node *clone;
- bool removed = remove_described_reference (n, rdesc);
- /* The reference might have been removed by IPA-CP. */
- if (removed
- && ipa_get_param_load_dereferenced (old_root_info, i))
- {
- new_root->create_reference (n, IPA_REF_LOAD, NULL);
- if (dump_file)
- fprintf (dump_file, "ipa-prop: ...replaced it with "
- "LOAD one from %s to %s.\n",
- new_root->dump_name (), n->dump_name ());
- }
-
- clone = cs->caller;
+ remove_described_reference (n, rdesc);
+ cgraph_node *clone = cs->caller;
while (clone->inlined_to
&& clone->ipcp_clone
&& clone != rdesc->cs->caller)
diff --git a/gcc/testsuite/gcc.dg/ipa/remref-6.c b/gcc/testsuite/gcc.dg/ipa/remref-6.c
index 7deae31..f31f4c1 100644
--- a/gcc/testsuite/gcc.dg/ipa/remref-6.c
+++ b/gcc/testsuite/gcc.dg/ipa/remref-6.c
@@ -20,5 +20,5 @@ void entry()
}
/* { dg-final { scan-ipa-dump "Removed a reference" "inline" } } */
-/* { dg-final { scan-ipa-dump "replaced it with LOAD" "inline" } } */
+/* { dg-final { scan-ipa-dump "adding LOAD reference" "inline" } } */
/* { dg-final { scan-tree-dump-not "builtin_exp" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/remref-7.c b/gcc/testsuite/gcc.dg/ipa/remref-7.c
new file mode 100644
index 0000000..b2c26ab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/remref-7.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-early-inlining -fno-ipa-sra -fdump-ipa-inline" } */
+
+int rglobal = 0;
+int g;
+
+int c;
+double *array;
+
+/* unused parameter */
+static void bar(int *p)
+{
+ int i;
+ for (i = 0; i < c; i++)
+ {
+ /* something big so that it is inlined second. */
+ array[i] = __builtin_exp(array[i]+1)*2;
+ }
+}
+
+void foo(int *p) {
+ g = *p;
+ bar(p);
+}
+
+void entry()
+{
+ foo(&rglobal);
+}
+
+/* { dg-final { scan-ipa-dump "Removed a reference" "inline" } } */
+/* { dg-final { scan-ipa-dump "adding LOAD reference" "inline" } } */
+
diff --git a/gcc/testsuite/gcc.dg/lto/pr103171_0.c b/gcc/testsuite/gcc.dg/lto/pr103171_0.c
new file mode 100644
index 0000000..5dc17d6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr103171_0.c
@@ -0,0 +1,11 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -O2 -flto -flto-partition=1to1 -fno-early-inlining -fno-ipa-sra -w } } } */
+
+extern void __attribute__((noinline)) entry(void);
+
+int
+main (int argc, char **argv)
+{
+ entry();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr103171_1.c b/gcc/testsuite/gcc.dg/lto/pr103171_1.c
new file mode 100644
index 0000000..39aed25
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr103171_1.c
@@ -0,0 +1,35 @@
+int rglobal = 0;
+
+volatile int g;
+volatile int c;
+volatile double *array;
+
+/* unused parameter */
+static void
+bar(int *p)
+{
+ int i;
+ for (i = 0; i < c; i++)
+ {
+ /* something big so that it is inlined second. */
+ array[i] = (array[i+1]+array[i]+1)*2;
+ }
+}
+
+void foo(int *p) {
+ g = *p;
+ bar(p);
+}
+
+void __attribute__((noinline))
+entry(void)
+{
+ foo(&rglobal);
+}
+
+void __attribute__((used))
+blah(int *p)
+{
+ bar(p);
+}
+