diff mbox series

Fix wrong code out of NRV + RSO + inlining

Message ID 4949065.31r3eYUQgx@fomalhaut
State New
Headers show
Series Fix wrong code out of NRV + RSO + inlining | expand

Commit Message

Eric Botcazou Sept. 11, 2024, 8:23 a.m. UTC
Hi,

the attached Ada testcase compiled with -O -flto exhibits a wrong code issue 
when the 3 optimizations NRV + RSO + inlining are applied to the same call: if 
the LHS of the call is marked write-only before inlining, then it will keep 
the mark after inlining although it may be read in GIMPLE from that point on.

The proposed fix is to always clear the flag during inlining in the RSO case.
Tested on x86-64/Linux, OK for the mainline?


2024-09-11  Eric Botcazou  <ebotcazou@adacore.com>

	* tree-inline.cc (declare_return_variable): Clear writeonly flag on
	a global variable used directly as the return slot.

2024-09-11  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/lto27.adb: New test.
	* gnat.dg/lto27_pkg1.ads, gnat.dg/lto27_pkg2.ads,
	gnat.dg/lto27_pkg2.adb, gnat.dg/lto27_pkg3.ads: New helper.

Comments

Richard Biener Sept. 11, 2024, 8:55 a.m. UTC | #1
On Wed, Sep 11, 2024 at 10:26 AM Eric Botcazou <botcazou@adacore.com> wrote:
>
> Hi,
>
> the attached Ada testcase compiled with -O -flto exhibits a wrong code issue
> when the 3 optimizations NRV + RSO + inlining are applied to the same call: if
> the LHS of the call is marked write-only before inlining, then it will keep
> the mark after inlining although it may be read in GIMPLE from that point on.
>
> The proposed fix is to always clear the flag during inlining in the RSO case.
> Tested on x86-64/Linux, OK for the mainline?

Hmm, it looks to me that the IPA analysis marking the variable readonly
in the first place is wrong - or that NRV may not be applied to such a variable
later.  Is NRV ever applied to say

static const S s = ...;

s = foo ();

thus a readonly declared LHS?

I think adjusting the varpool flag just during inline materialization
doesn't resolve
issues that appear when the wrong flag caused other wrong IPA
decisions for example.

Richard.

>
> 2024-09-11  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * tree-inline.cc (declare_return_variable): Clear writeonly flag on
>         a global variable used directly as the return slot.
>
> 2024-09-11  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * gnat.dg/lto27.adb: New test.
>         * gnat.dg/lto27_pkg1.ads, gnat.dg/lto27_pkg2.ads,
>         gnat.dg/lto27_pkg2.adb, gnat.dg/lto27_pkg3.ads: New helper.
>
>
> --
> Eric Botcazou
Eric Botcazou Sept. 11, 2024, 10:38 a.m. UTC | #2
> Hmm, it looks to me that the IPA analysis marking the variable readonly
> in the first place is wrong - or that NRV may not be applied to such a
> variable later.  Is NRV ever applied to say
> 
> static const S s = ...;
> 
> s = foo ();
> 
> thus a readonly declared LHS?

But NRV is only an example and not necessary, as you may read a RESULT_DECL in 
the callee.  So the combination is actually just RSO + inlining if the callee 
happens to read RESULT_DECL.
Richard Biener Sept. 11, 2024, 1:28 p.m. UTC | #3
On Wed, Sep 11, 2024 at 12:38 PM Eric Botcazou <botcazou@adacore.com> wrote:
>
> > Hmm, it looks to me that the IPA analysis marking the variable readonly
> > in the first place is wrong - or that NRV may not be applied to such a
> > variable later.  Is NRV ever applied to say
> >
> > static const S s = ...;
> >
> > s = foo ();
> >
> > thus a readonly declared LHS?
>
> But NRV is only an example and not necessary, as you may read a RESULT_DECL in
> the callee.  So the combination is actually just RSO + inlining if the callee
> happens to read RESULT_DECL.

Sure, but then the same argument is that with RSO marking the variable
as write-only
is wrong (or changing the call to use RSO for a write-only variable) -
unless the callee
never reads from RESULT_DECL.

Richard.

>
> --
> Eric Botcazou
>
>
diff mbox series

Patch

diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
index f31a34ac410..2bb1e1602b2 100644
--- a/gcc/tree-inline.cc
+++ b/gcc/tree-inline.cc
@@ -3782,6 +3782,11 @@  declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 	  gcc_assert (TREE_CODE (var) != SSA_NAME);
 	  if (TREE_ADDRESSABLE (result))
 	    mark_addressable (var);
+	  /* RESULT may also be read in the callee, typically because the NRV
+	     optimization has been applied to the function, so VAR may also be
+	     read from now on.  */
+	  if (VAR_P (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var)))
+	    varpool_node::get (var)->writeonly = 0;
 	}
       if (DECL_NOT_GIMPLE_REG_P (result)
 	  && DECL_P (var))