Bug 20083 - Missed optimization with conditional and basically ||
Summary: Missed optimization with conditional and basically ||
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.0.0
: P2 enhancement
Target Milestone: 14.0
Assignee: Andrew Pinski
URL:
Keywords: missed-optimization
Depends on: 89263 96923
Blocks:
  Show dependency treegraph
 
Reported: 2005-02-19 16:50 UTC by Andrew Pinski
Modified: 2023-06-07 02:45 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-11-17 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2005-02-19 16:50:55 UTC
The following three functions should result in the same assembly (the last is the best, branchless and 
only does one compare):
int f(int i, int j, int l)
{
  int k = 0;
  if (i)
   k = 1;
  if (j)
   k = 1; 
  if (l)
    k = 1;
  return k;
}
int f1(int i, int j, int l)
{
  int k = 0;
  if (i)
   k = 1;
  else if (j)
   k = 1; 
  else if (l)
   k = 1;
  return k;
}
int f2(int i, int j, int l)
{
  return i||j||l;
}

Note I came up with this testcase after adding code like the above code to gcc and I was wondering how 
we optimizated it.
Comment 1 Andrew Pinski 2005-02-22 18:27:09 UTC
Confirmed.
Comment 2 Andrew Pinski 2012-01-21 22:04:34 UTC
I will take care of this one too.
Comment 3 Andrew Pinski 2020-01-18 06:15:38 UTC
Here is another testcase which should produce the same code:
int f3(int i, int j, int l)
{
  int t = i | j;
  _Bool t1 = l != 0;
  _Bool t2 = t ? 1 : t1;
  return t2;
}

int f4(int i, int j, int l)
{
  int t = i | j;
  _Bool t1 = l != 0;
  _Bool t2;
  if (t)
   t2 = 1;
  else
   t2 = t1;
  return t2;
}


--- CUT ----
Note f1, f2, f3 and f4 all produce the same code now.
f comes close now, but still requires work:
        orr     w0, w0, w1
        cmp     w0, 0
        cset    w0, ne
        cmp     w2, 0
        csinc   w0, w0, wzr, eq
it does an ifcvt on the rtl level to get the csinc.
f4 is exactly what f2 looks like at the .optimized as the input to the gimple and reassoc can optimize this case but only if we sink l != 0 into the if statement.

So this is another improvement needed for reassoc really.
I will look at this next week or the week after.
Comment 4 Andrew Pinski 2020-01-18 06:19:09 UTC
Take f4, if we compile with -O1 -fno-tree-sink, you will see the behavior we get for f.
Comment 5 Andrew Pinski 2021-06-03 00:56:39 UTC
Looks like only f is broken now.
in phiopt3:
  _8 = i_4(D) != 0;
  _9 = (int) _8;
  if (j_5(D) != 0)
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

  <bb 3> [local count: 536870913]:

  <bb 4> [local count: 1073741824]:
  # k_2 = PHI <_9(2), 1(3)>
  if (l_6(D) != 0)
    goto <bb 5>; [50.00%]
  else
    goto <bb 6>; [50.00%]

  <bb 5> [local count: 536870913]:

  <bb 6> [local count: 1073741824]:
  # k_3 = PHI <k_2(4), 1(5)>

Hmm, this looks like it could be fixed with PR 96923.  I will test it again once I fix that one.
Comment 6 Andrew Pinski 2023-05-24 00:03:48 UTC
The patch simple which fixes PR 89263.
Comment 7 Andrew Pinski 2023-06-07 00:30:09 UTC
Patch submitted:
https://gcc.gnu.org/pipermail/gcc-patches/2023-June/620829.html
Comment 8 GCC Commits 2023-06-07 02:43:59 UTC
The trunk branch has been updated by Andrew Pinski <pinskia@gcc.gnu.org>:

https://gcc.gnu.org/g:64d90d06d2db43538c8a45adbb3d74842f7868ae

commit r14-1597-g64d90d06d2db43538c8a45adbb3d74842f7868ae
Author: Andrew Pinski <apinski@marvell.com>
Date:   Wed May 24 07:08:45 2023 +0000

    Add match patterns for `a ? onezero : onezero` where one of the two operands are constant
    
    This adds a match pattern that are for boolean values
    that optimizes `a ? onezero : 0` to `a & onezero` and
    `a ? 1 : onezero` to `a | onezero`.
    
    This was reported a few times and I thought I would finally
    add the match pattern for this.
    
    This hits a few times in GCC itself too.
    
    Notes on the testcases:
    * phi-opt-2.c: This now is optimized to `a & b` in phiopt rather than ifcombine
    * phi-opt-25b.c: The test part that was failing was parity which now gets `x & y` treatment.
    * ssa-thread-21.c: there is no longer a threading opportunity, so need to disable phiopt.
      Note PR 109957 is filed for the now missing optimization in that testcase too.
    
    gcc/ChangeLog:
    
            PR tree-optimization/89263
            PR tree-optimization/99069
            PR tree-optimization/20083
            PR tree-optimization/94898
            * match.pd: Add patterns to optimize `a ? onezero : onezero` with
            one of the operands are constant.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/phi-opt-2.c: Adjust the testcase.
            * gcc.dg/tree-ssa/phi-opt-25b.c: Adjust the testcase.
            * gcc.dg/tree-ssa/ssa-thread-21.c: Disable phiopt.
            * gcc.dg/tree-ssa/phi-opt-27.c: New test.
            * gcc.dg/tree-ssa/phi-opt-28.c: New test.
            * gcc.dg/tree-ssa/phi-opt-29.c: New test.
            * gcc.dg/tree-ssa/phi-opt-30.c: New test.
            * gcc.dg/tree-ssa/phi-opt-31.c: New test.
            * gcc.dg/tree-ssa/phi-opt-32.c: New test.
Comment 9 Andrew Pinski 2023-06-07 02:45:56 UTC
Fixed finally (after 18 years) of messing around with PHI-OPT :).