[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2023-06-07 Thread amacleod at redhat dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

--- Comment #13 from Andrew Macleod  ---
(In reply to Andrew Pinski from comment #12)
> Aldy or Andrew, why in conv1 we don't get a range for 
>   SR.4_4 = sD.8798._M_valueD.7665;
> 
> Even though the range we have is [-1,1] according to the
> __builtin_unreachable()?
> It seems like we should get that range. Once we do get that the code works.
> E.g. If we add:
>   signed char *t = (signed char*)
>   signed char tt = *t;
>   if (tt < -1 || tt > 1) __builtin_unreachable();
> 
> In the front before the other ifs, we get the code we are expecting.
> 
> conv2 has a similar issue too, though it has also a different issue of
> ordering for the comparisons.

its because the unreachable is after the branches, and we have multiple uses of
SR.4_4 before the unreachable.

   [local count: 1073741824]:
  SR.4_4 = s._M_value;
  if (SR.4_4 == -1)
goto ; [50.00%]
  else
goto ; [50.00%]

   [local count: 536870913]:
  if (SR.4_4 == 0)
goto ; [50.00%]
  else
goto ; [50.00%]

   [local count: 268435456]:
  if (SR.4_4 == 1)
goto ; [100.00%]
  else
goto ; [0.00%]

   [count: 0]:
  __builtin_unreachable ();

   [local count: 1073741824]:
  # _1 = PHI <-1(2), 0(3), 1(4)>

We know when we get to bb5 that SR.4_4 is [-1, 1] for sure.
But we dont know that before we reach that spot.
if there was a call to 
  foo(SR.4_4)
in bb 3 for instance,   we wouldn't be able to propagate [-1,1] to the call to
foo because it happens before we know for sure.and foo may go and do
something if it has a value of 6 and exit the compilation, thus never
returning.

So we can only provide a range of [-1, 1] AFTER the unreachable, or if there is
only a single use of it.. the multiples uses are what tricks it.

This has come up before.  we need some sort of backwards propagation that can
propagate discovered values earlier into the IL to a point where it is known to
be safe (ie, it wouldnt be able to propagate it past a call to foo() for
instance)
In cases like this, we could discover it is safe to propagate that range back
to the def point, and then we could set the global.

Until we add some smarts, either to the builtin unreachable elimination code,
or elsewhere, which is aware of how to handle such side effects, we can't set
the global because we dont know if it is safe at each use before the
unreachable call.

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2023-06-07 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

Andrew Pinski  changed:

   What|Removed |Added

 CC||aldyh at gcc dot gnu.org,
   ||amacleod at redhat dot com

--- Comment #12 from Andrew Pinski  ---
Aldy or Andrew, why in conv1 we don't get a range for 
  SR.4_4 = sD.8798._M_valueD.7665;

Even though the range we have is [-1,1] according to the
__builtin_unreachable()?
It seems like we should get that range. Once we do get that the code works.
E.g. If we add:
  signed char *t = (signed char*)
  signed char tt = *t;
  if (tt < -1 || tt > 1) __builtin_unreachable();

In the front before the other ifs, we get the code we are expecting.

conv2 has a similar issue too, though it has also a different issue of ordering
for the comparisons.

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2022-03-14 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

--- Comment #11 from Jakub Jelinek  ---
(In reply to Oliver Schönrock from comment #10)
> I agree the switch optimisation is better, but...
> 
>  shouldn't std::bit_cast prevent incorrect casting with different underlying
> implementaion? (ie if the size doesn't match, and the size could be deduced
> with TMP) 

The size can be deduced, yes.  What the bits actually mean can't be.

> and "unordered value" doesn't apply to std::strong_ordering?

Sure, but this PR isn't just about strong_ordering, same problem applies for
partial_ordering.
And actually not just those, but any case of some set of enumerators or macros
where you don't know the values exactly and mapping them to or from a set of
integer constants, ideally with 1:1 mapping but not guaranteed that way.

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2022-03-14 Thread oschonrock at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

--- Comment #10 from Oliver Schönrock  ---
I agree the switch optimisation is better, but...

 shouldn't std::bit_cast prevent incorrect casting with different underlying
implementaion? (ie if the size doesn't match, and the size could be deduced
with TMP) 

and "unordered value" doesn't apply to std::strong_ordering?

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2022-03-14 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org

--- Comment #9 from Jakub Jelinek  ---
That one isn't portable, relies on both the strong_ordering underlying
implementation using an 8-bit integer member rather than something else, and
also hardcodes the exact values where in C++ the -1 / 0 / 1 are exposition only
and unordered value is -127 rather than what gcc uses (2).
By writing a series of ifs or switch one achieves portability and we'd just
like to get efficient code if the values the user chose match those used by the
implementation.

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2022-03-14 Thread oschonrock at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

--- Comment #8 from Oliver Schönrock  ---
how about:

#include 
#include 
#include 

int conv3(std::strong_ordering s){
return std::bit_cast(s);
}
std::strong_ordering conv4(int i){
return std::bit_cast(static_cast(i));
}


conv3(std::strong_ordering):
movsbl  %dil, %eax
ret
conv4(int):
movl%edi, %eax
ret


https://godbolt.org/z/szP5MGq4T

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2021-08-03 Thread marxin at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

Martin Liška  changed:

   What|Removed |Added

   See Also||https://gcc.gnu.org/bugzill
   ||a/show_bug.cgi?id=92005

--- Comment #7 from Martin Liška  ---
> So here is the proposed pipeline:
> iftoswitch - change to do it even without an heurstics
> sink
> switchconv
> switchlower - early

This one is also not ideal as there might be an optimization that eliminates
some of the switch case branches.

Note that we have a similar issue PR92005.

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2021-08-03 Thread marxin at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

--- Comment #6 from Martin Liška  ---
(In reply to Marc Glisse from comment #3)
> I thought we had code to recognize a switch that represents a linear
> function, I was hoping that it would kick in with your hoisting patch...

Yep, we have the code but as mentioned the sinking needs to happen first.
Otherwise, you'll see:

g++ pr94566.C -O2 -fdump-tree-switchconv=/dev/stdout -std=gnu++2a

;; Function conv2 (_Z5conv2i, funcdef_no=90, decl_uid=8463, cgraph_uid=59,
symbol_order=88)

beginning to process the following SWITCH statement (pr94566.C:4) : --- 
switch (i_2(D))  [INV], case -1:  [INV], case 0:  [INV],
case 1:  [INV]>

Bailing out - bad case - a non-final BB not empty

struct strong_ordering conv2 (int i)
{
  struct strong_ordering D.8476;

   :
  switch (i_2(D))  [INV], case -1:  [INV], case 0: 
[INV], case 1:  [INV]>

   :
:
  D.8476._M_value = -1;
  goto ; [INV]

   :
:
  D.8476._M_value = 0;
  goto ; [INV]

   :
:
  D.8476._M_value = 1;
  goto ; [INV]

   :
:
  __builtin_unreachable ();

   :
  return D.8476;

}

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2021-08-03 Thread marxin at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

Martin Liška  changed:

   What|Removed |Added

 CC||marxin at gcc dot gnu.org

--- Comment #5 from Martin Liška  ---
(In reply to Richard Biener from comment #2)
> I've verified my old fix for PR33315 does

Can you please show me which patch from the PR does that?

> 
> still not optimized further tho.

When does the sinking happen in the optimization pipeline?

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2021-06-14 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

Andrew Pinski  changed:

   What|Removed |Added

   Last reconfirmed|2020-04-13 00:00:00 |2021-6-14

--- Comment #4 from Andrew Pinski  ---
I wonder if we should always convert if-cases to switches and then do
switchconv and then lower the smaller ones (3 if max) right after switchconv
and then lower the rest in late as we do right now.  This should get the conv1
case.

The conv2 case problem is don't sink until late and never redo switchconv.

So here is the proposed pipeline:
iftoswitch - change to do it even without an heurstics
sink
switchconv
switchlower - early

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2020-05-15 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566
Bug 94566 depends on bug 33315, which changed state.

Bug 33315 Summary: stores not commoned by sinking
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33315

   What|Removed |Added

 Status|ASSIGNED|RESOLVED
 Resolution|--- |FIXED

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2020-04-15 Thread glisse at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

--- Comment #3 from Marc Glisse  ---
I thought we had code to recognize a switch that represents a linear function,
I was hoping that it would kick in with your hoisting patch...

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2020-04-15 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

Richard Biener  changed:

   What|Removed |Added

 Blocks|11832, 33315|
 Depends on||33315

--- Comment #2 from Richard Biener  ---
I've verified my old fix for PR33315 does

t.C:11:45: optimized: sinking common stores to D.8528._M_value
...
conv2 (int i)
{
  struct strong_ordering D.8528;
  int _7;

   [local count: 1073741817]:
  switch (i_2(D))  [0.00%], case -1:  [33.33%], case 0: 
[33.33%], case 1:  [33.33%]>

   [local count: 357913942]:
:
  goto ; [100.00%]

   [local count: 357913942]:
:
  goto ; [100.00%]

   [count: 0]:
:
  __builtin_unreachable ();

   [local count: 1073741824]:
  # _7 = PHI <-1(2), 0(3), 1(4)>
:
  D.8528._M_value = _7;
  return D.8528;

still not optimized further tho.


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11832
[Bug 11832] Optimization of common stores in switch statements
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33315
[Bug 33315] stores not commoned by sinking

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2020-04-14 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

--- Comment #1 from Richard Biener  ---
So for conv2 the most immediate issue is that we're failing to sink and common
the assignment to D.8516._M_value (I had patches for this).

conv2 (int i)
{
  int i_2(D) = i;
  struct strong_ordering D.8516;

   [local count: 1073741824]:
  if (i_2(D) == 0)
goto ; [33.33%]
  else
goto ; [66.67%]

   [local count: 1073741824]:
  if (i_2(D) == 1)
goto ; [50.00%]
  else
goto ; [50.00%]

   [local count: 357878150]:
  D.8516._M_value = -1;
  goto ; [100.00%]

   [local count: 357878150]:
  D.8516._M_value = 0;
  goto ; [100.00%]

   [local count: 357878150]:
  D.8516._M_value = 1;

   [local count: 1073634451]:
  return D.8516;

for conv1 this is a missed phi-opt, at phiopt2 time:

conv1 (struct strong_ordering s)
{
  int SR.4;
  int _1;

   [local count: 1073741824]:
  SR.4_4 = s._M_value;
  if (SR.4_4 == -1)
goto ; [50.00%]
  else
goto ; [50.00%]

   [local count: 536870913]:
  if (SR.4_4 == 0)
goto ; [50.00%]
  else
goto ; [50.00%]

   [local count: 268435456]:
  if (SR.4_4 == 1)
goto ; [100.00%]
  else
goto ; [0.00%]

   [count: 0]:
  __builtin_unreachable ();

   [local count: 1073741824]:
  # RANGE [-1, 1]
  # _1 = PHI <-1(2), 0(3), 1(4)>
  return _1;

it's a bit of a convoluted case of course but the only chance to pattern
match this ...

[Bug tree-optimization/94566] conversion between std::strong_ordering and int

2020-04-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94566

Jonathan Wakely  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2020-04-13
   See Also||https://gcc.gnu.org/bugzill
   ||a/show_bug.cgi?id=94006
 Ever confirmed|0   |1