[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2024-03-15 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

--- Comment #8 from Andrew Pinski  ---
For the non-static case, IPA-SRA has:
```
Summary for node int foo2(two_ints)/0:
  Returns value
  Descriptor for parameter 0:
param_size_limit: 8, size_reached: 4
* Access to unit offset: 0, unit size: 4, type: int, alias_ptr_type: int *,
certain


...
Function int foo2(two_ints)/0 disqualified because it cannot be made local.
```

[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2024-03-15 Thread eyalroz1 at gmx dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

--- Comment #7 from Eyal Rozenberg  ---
(In reply to Andrew Pinski from comment #6)
> I am think this can be closed as fixed ...

Well, my example no longer generates two loads. However


> IPA-SRA does handle this if the function is static.
> 
> Also mod-ref handles this if the function takes a pointer instead of a
> struct.

are both not the case for my example.

So, while I don't understand know why this works now, it does, and I suppose
you can close this.

[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2024-03-14 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

Andrew Pinski  changed:

   What|Removed |Added

   Severity|normal  |enhancement

--- Comment #6 from Andrew Pinski  ---
IPA-SRA does handle this if the function is static.

Also mod-ref handles this if the function takes a pointer instead of a struct.
Aka:
```
 struct two_ints { int x, y; };

  __attribute__((noinline)) int foo2(struct two_ints *s)
  {
return s->x;
  }

  int bar2(int* a)
  {
struct two_ints ti = { a[5], a[10] };
int b = foo2();
return b * b;
  }
```

The store to ti.x is only there now.

I am think this can be closed as fixed ...

[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2019-03-04 Thread jamborm at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

--- Comment #5 from Martin Jambor  ---
(In reply to Eyal Rozenberg from comment #4)
> > In the first excample, the interproceudral constant propagation pass
> > (IPA-CP) found that foo1 is so small that copying all of it might be
> > worth not passing the unused argument and so it does, that is why
> > you'll find function foo1 twice in the assembly. 
> 
> Why does this have anything to do with constant propagation? I also don't
> understand the sense in two identical copies.

The transformation literally removes a parameter from a function.  All
(direct) callers in the same compilation unit then call the new clone,
all indirect clones and callers from other compilation units call the
old one, with the old calling convention.  I understand that in your
simple testcase that does not matter but in others it might (and
IPA-CP is a high-level pass that does not know about physical
registers, calling conventions etc.).

> 
> It also sounds like "the wrong optimization" is being used if it's not about
> noticing unused parameters.

You can call it that way if you like to.  It was just easy to add
there, it makes a good job and has no practical disadvantages.

> 
> > This functionality
> > in the pass is there just "on the side" and it is not easy to make it
> > also work with aggegates, not even desireable (that is the job of a
> > different pass, see below).
> >
> > Both examples are compiled better if you make foo1 and foo2 static.
> 
> This really makes no sense to me! bar() is not affected by other TUs at
> all...

IPA-SRA primarily changes foo.  

> 
> > In the latter case, you get exactly what you want, the structure is be
> > split and only the used part survives.  In the first example, you
> > don't get a clone emitted which you probably don't need.  Both of
> > these transformation are done by a pass called interprocedural scalar
> > replacement of aggregates (IPA-SRA), which specifically also aims to
> > remove unused arguments, but it never creates multiple clones.
> 
> I like this pass :-) ... so, why does it work for the static case with
> bar2() but doesn't work with bar1() ?

I don't understand your question, just make foo1 and/or foo2 static
and it will trigger.   The pass needs to adjust all callers and
therefore only works on static functions because otherwise there may
be other call in other compilation units.

> 
> > I'm afraid you'd need to provide a strong real-world use-case to make
> > me investigate how to make IPA-SRA clone so you might not need static
> > and/or LTO because that would mean devising a cost/benefit
> > (size/speedup) heuristics and that is not easy.
> 
> For now I'm just trying to understand why this isn't already happening. Then
> I'll perhaps try to understand why clang does do this.
> 
> But - don't necessarily clone. IIUC,  cloning would possibly mean removing
> that parameter even though it's a field of a struct. But even if you _don't_
> clone, functions calling foo() should still not have to initialize that
> member. It seems like we're talking about different optimizations.

Indeed, you really have a IPA-DSE in your mind (DSE stands for dead
store elimination), that would only affect callers.  We don't have
that, it might be an alternative for to IPA-SRA when we do cannot or
do not want to clone.

[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2019-03-04 Thread eyalroz at technion dot ac.il
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

--- Comment #4 from Eyal Rozenberg  ---

> In the first excample, the interproceudral constant propagation pass
> (IPA-CP) found that foo1 is so small that copying all of it might be
> worth not passing the unused argument and so it does, that is why
> you'll find function foo1 twice in the assembly. 

Why does this have anything to do with constant propagation? I also don't
understand the sense in two identical copies.

It also sounds like "the wrong optimization" is being used if it's not about
noticing unused parameters.

> This functionality
> in the pass is there just "on the side" and it is not easy to make it
> also work with aggegates, not even desireable (that is the job of a
> different pass, see below).
>
> Both examples are compiled better if you make foo1 and foo2 static.

This really makes no sense to me! bar() is not affected by other TUs at all...

> In the latter case, you get exactly what you want, the structure is be
> split and only the used part survives.  In the first example, you
> don't get a clone emitted which you probably don't need.  Both of
> these transformation are done by a pass called interprocedural scalar
> replacement of aggregates (IPA-SRA), which specifically also aims to
> remove unused arguments, but it never creates multiple clones.

I like this pass :-) ... so, why does it work for the static case with bar2()
but doesn't work with bar1() ?


> I'm afraid you'd need to provide a strong real-world use-case to make
> me investigate how to make IPA-SRA clone so you might not need static
> and/or LTO because that would mean devising a cost/benefit
> (size/speedup) heuristics and that is not easy.

For now I'm just trying to understand why this isn't already happening. Then
I'll perhaps try to understand why clang does do this.

But - don't necessarily clone. IIUC,  cloning would possibly mean removing that
parameter even though it's a field of a struct. But even if you _don't_ clone,
functions calling foo() should still not have to initialize that member. It
seems like we're talking about different optimizations.

[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2019-03-04 Thread jamborm at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

Martin Jambor  changed:

   What|Removed |Added

 CC||jamborm at gcc dot gnu.org

--- Comment #3 from Martin Jambor  ---
In the first excample, the interproceudral constant propagation pass
(IPA-CP) found that foo1 is so small that copying all of it might be
worth not passing the unused argument and so it does, that is why
you'll find function foo1 twice in the assembly.  This functionality
in the pass is there just "on the side" and it is not easy to make it
also work with aggegates, not even desireable (that is the job of a
different pass, see below).

Both examples are compiled better if you make foo1 and foo2 static.
In the latter case, you get exactly what you want, the structure is be
split and only the used part survives.  In the first example, you
don't get a clone emitted which you probably don't need.  Both of
these transformation are done by a pass called interprocedural scalar
replacement of aggregates (IPA-SRA), which specifically also aims to
remove unused arguments, but it never creates multiple clones.

If you cannot make these functions static, you need link-time
optimization (LTO, option -flto) because you need information about
one compilation unit to optimize others.  The current IPA-SRA cannot
unfortunately make use of it but I have a replacement for it that can,
hopefully it will be part of GCC 10.

I'm afraid you'd need to provide a strong real-world use-case to make
me investigate how to make IPA-SRA clone so you might not need static
and/or LTO because that would mean devising a cost/benefit
(size/speedup) heuristics and that is not easy.

[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2019-03-04 Thread eyalroz at technion dot ac.il
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

--- Comment #2 from Eyal Rozenberg  ---
(In reply to Richard Biener from comment #1)
> You are looking for IPA DSE 

I'm not a compiler expert and don't know what this means. Even literally, I
don't know what these acronyms stand for.

> by marshalling through a struct you make GCCs job a lot harder...  

Well, first - yes, I suppose this could make things harder. However, as GCC
does its magic, I presume that at some point the struct abstraction is lost,
and we only have code which passes values to another function in registers, and
one of these values is unused. So at some point along the way this might be
easier than analyzing structs.

> "pro-active" IPA-SRA might help here,

Again, I have no idea what that is... could I trouble you to elaborate just a
bit more?

[Bug ipa/89567] [missed-optimization] Should not be initializing unused struct parameter members

2019-03-04 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89567

Richard Biener  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2019-03-04
 CC||marxin at gcc dot gnu.org,
   ||mjambor at suse dot cz
  Component|tree-optimization   |ipa
 Ever confirmed|0   |1

--- Comment #1 from Richard Biener  ---
You are looking for IPA DSE - by marshalling through a struct you make GCCs
job a lot harder...  "pro-active" IPA-SRA might help here, or making its
analysis stronger by looking for (partial) aggregate argument usage...

Don't hold your breath.