[PATCH] IPA: MODREF should skip EAF_* flags for indirect calls

Jan Hubicka hubicka@ucw.cz
Sun Aug 22 17:32:14 GMT 2021


> Thanks for looking into this bug - it is interesting that ipa-pta
> requires !EAF_NOCLOBBER when function is called...
> 
> I have some work done on teaching ipa-modref (and other propagation
> passes) to use ipa-devirt info when the full set of callees is known.
> This goes oposite way.
> 
> You can drop flags only when callee == NAME and you can just frop
> EAF_NOCLOBBER.  For example in testcase
> 
> struct a {
>   void (*foo)();
>   void *bar;
> }
> 
> void wrap (struct a *a)
> {
>   a->foo ();
> }
> 
> will prevent us from figuring out that bar can not be modified when you
> pass non-ecaping instance of struct a to wrap.
> 

I am testing this updated patch which implements that.  I am not very
happy about this (it punishes -fno-ipa-pta path for not very good
reason), but we need bugfix for release branch.  

It is very easy now to add now EAF flags at modref side
so we can track EAF_NOT_CALLED. 
tree-ssa-structalias side is always bit anoying wrt new EAF flags
because it has three copies of the code building constraints for call
(for normal, pure and const).

Modref is already tracking if function can read/modify global memory.  I
plan to add flags for NRC and link chain and then we can represent
effect of ECF_CONST and PURE by simply adding flags.  I would thus would
like to merge that code.  We do various optimizations to reduce amount
of constriants produced, but hopefully this is not very important (or
can be implemented by special casing in unified code).

Honza

gcc/ChangeLog:

2021-08-22  Jan Hubicka  <hubicka@ucw.cz>
	    Martin Liska  <mliska@suse.cz>

	* ipa-modref.c (analyze_ssa_name_flags): Indirect call implies
	~EAF_NOCLOBBER.

gcc/testsuite/ChangeLog:

2021-08-22  Jan Hubicka  <hubicka@ucw.cz>
	    Martin Liska  <mliska@suse.cz>

	* gcc.dg/lto/pr101949_0.c: New test.
	* gcc.dg/lto/pr101949_1.c: New test.

diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index fafd804d4ba..549153865b8 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -1700,6 +1700,15 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth,
       else if (gcall *call = dyn_cast <gcall *> (use_stmt))
 	{
 	  tree callee = gimple_call_fndecl (call);
+
+	  /* IPA PTA internally it treats calling a function as "writing" to
+	     the argument space of all functions the function pointer points to
+	     (PR101949).  We can not drop EAF_NOCLOBBER only when ipa-pta
+	     is on since that would allow propagation of this from -fno-ipa-pta
+	     to -fipa-pta functions.  */
+	  if (gimple_call_fn (use_stmt) == name)
+	    lattice[index].merge (~EAF_NOCLOBBER);
+
 	  /* Return slot optimization would require bit of propagation;
 	     give up for now.  */
 	  if (gimple_call_return_slot_opt_p (call)
diff --git a/gcc/testsuite/gcc.dg/lto/pr101949_0.c b/gcc/testsuite/gcc.dg/lto/pr101949_0.c
new file mode 100644
index 00000000000..142dffe8780
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr101949_0.c
@@ -0,0 +1,20 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O2 -fipa-pta -flto -flto-partition=1to1" } } */
+
+extern int bar (int (*)(int *), int *);
+
+static int x;
+
+static int __attribute__ ((noinline)) foo (int *p)
+{
+  *p = 1;
+  x = 0;
+  return *p;
+}
+
+int main ()
+{
+  if (bar (foo, &x) != 0)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr101949_1.c b/gcc/testsuite/gcc.dg/lto/pr101949_1.c
new file mode 100644
index 00000000000..871d15c9bfb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr101949_1.c
@@ -0,0 +1,4 @@
+int __attribute__((noinline,noclone)) bar (int (*fn)(int *), int *p)
+{
+  return fn (p);
+}


More information about the Gcc-patches mailing list