[Bug tree-optimization/109112] [[assume(...)]] is not taken into account for structs

2023-07-14 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109112

--- Comment #8 from Jakub Jelinek  ---
(In reply to Jason Merrill from comment #7)
> Why don't the existing optimizations work on the artificial function the
> same as any other function?  i.e. like
> 
> struct S { bool x; };
> void do_something();
> inline void assumption_1 (const S& s) noexcept {
>   if (s.x) __builtin_unreachable ();
> }
> void fn(S s) {
>   assumption_1 (s);
>   if (s.x) do_something();
> }
> 
> which is also optimized as expected.

Because the assumptions have different representation in the IL.
While normal calls look like:
  ret = foo (arg1, arg2, arg3);
and we can inline those etc., because the assumptions potentially contain
side-effects which shouldn't be evaluated and therefore should e.g. not be
inlined nor assumed that they are actually called, the representation is like:
  .ASSUME (, arg1, arg2, arg3);
where foo is that artificial assumption function which takes arg1, arg2, arg3.
The above behaves like if (!foo (arg1, arg2, arg3)) __builtin_unreachable ();
except that the function actually isn't called (nor emitted into assembly
etc.).
The assumption is if this function would be called and returned false at this
spot,
it would be UB.
So, VRP walks the assumption function (after optimizations are performed on it,
e.g. inlining into those and various other optimizations) backwards from the
return value starting with [1, 1] and from that derives ranges for the
arguments.

Similarly to how for functions which aren't inlined but can be e.g. cloned it
is essential to get IPA SRA and IPA CP etc. optimizations to tweak the
arguments of functions (scalarize them, remove unneeded ones, replace others),
it is needed
that we optimize the assumptions similarly.  The assumption functions should be
always static and often will have a single reference (unless inlined multiple
times / loop unrolled), so it is just fine to tweak them, just those
optimizations will need
to special case the IFN_ASSUME internal calls and treat
.ASSUME (, arg1, arg2, arg3);
more like
foo (arg1, arg2, arg3);
(i.e. off by one argument and treat it as if there was a call edge from the
.ASSUME
caller to foo.

[Bug tree-optimization/109112] [[assume(...)]] is not taken into account for structs

2023-07-13 Thread jason at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109112

--- Comment #7 from Jason Merrill  ---
In an email thread Jakub wrote:

Only the simplest assumptions in [[assume(cond)]] where there clearly aren't
any
side-effects no risks of them are lowered to if (!cond) __builtin_unreachable
();
in the IL, anything else goes into the condition being outlined in a
separate artificial function and an internal function recording the
assumption in the IL.
The optimizers then can optimize both the artificial function and the
caller.
The missed optimization thing is that currently only the value range
propagation is able to take advantage of the assumptions, and VRP
is only able to deal with scalars.
We have interprocedural optimizations like IPA scalar replacement of
aggregates etc., where we can optimize passing aggregates at function
boundaries to passing just some scalars from them if the rest isn't needed
etc., but because the assumptions aren't normal calls they'd need tweaks to
be able to optimize the assumptions too so that VRP could take advantage of
those.


Why don't the existing optimizations work on the artificial function the same
as any other function?  i.e. like

struct S { bool x; };
void do_something();
inline void assumption_1 (const S& s) noexcept {
  if (s.x) __builtin_unreachable ();
}
void fn(S s) {
  assumption_1 (s);
  if (s.x) do_something();
}

which is also optimized as expected.

[Bug tree-optimization/109112] [[assume(...)]] is not taken into account for structs

2023-07-13 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109112

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jamborm at gcc dot gnu.org

--- Comment #6 from Jakub Jelinek  ---
CCing Martin, I don't have sufficient experience with IPA SRA nor IPA CP to be
able to handle this.

[Bug tree-optimization/109112] [[assume(...)]] is not taken into account for structs

2023-07-13 Thread jason at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109112

Jason Merrill  changed:

   What|Removed |Added

 CC||jason at gcc dot gnu.org
   Last reconfirmed||2023-07-13
 Status|UNCONFIRMED |NEW
 Ever confirmed|0   |1

--- Comment #5 from Jason Merrill  ---
Note that the __builtin_unreachable variant is optimized as expected:

struct S { bool x; };
void do_something();
void fn(S s) {
  if (s.x) __builtin_unreachable ();
  if (s.x) do_something();
}

It's unfortunate that [[assume (x)]] is currently so much less useful than if
(!x) __builtin_unreachable(), which expresses almost the same thing.

[Bug tree-optimization/109112] [[assume(...)]] is not taken into account for structs

2023-03-13 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109112

--- Comment #4 from Jakub Jelinek  ---
One way to improve this case would be to teach IPA SRA/CP etc. to perform some
optimizations on the .ASSUME ifn calls and their corresponding functions, in
this case if SRA would turn the argument from aggregate to scalar.

[Bug tree-optimization/109112] [[assume(...)]] is not taken into account for structs

2023-03-13 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109112

--- Comment #3 from Andrew Pinski  ---
I also suspect this is a dup of bug 109045 really.