https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126139

            Bug ID: 126139
           Summary: phiopt does not if-convert half diamonds with multiple
                    PHIs
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---

734.vpr_r from SPEC2026 has a missed opportunity on GCC (~6%) due to missed
if-conversion for the testcase:

    void
    minmax (const int *a, int n, int *pmin, int *pmax)
    {
      int lo = a[0];
      int hi = a[0];
      for (int i = 1; i < n; i++)
        {
          int x = a[i];
          if (x < lo)
            lo = x;
          else if (x > hi)
            hi = x;
        }
      *pmin = lo;
      *pmax = hi;
    }

LLVM generates for aarch64 at -O3:
minmax:
        ldr     w8, [x0]
        cmp     w1, #2
        b.lt    .LBB0_4
        mov     w10, w1
        add     x9, x0, #4
        sub     x11, x10, #1
        mov     w10, w8
.LBB0_2:
        ldr     w12, [x9], #4
        cmp     w12, w10
        csel    w13, w12, w10, gt
        cmp     w12, w8
        csel    w10, w10, w13, lt
        csel    w8, w12, w8, lt
        subs    x11, x11, #1
        b.ne    .LBB0_2
        str     w8, [x2]
        str     w10, [x3]
        ret
.LBB0_4:
        str     w8, [x2]
        str     w8, [x3]
        ret

whereas GCC generates fewer CSELs. At late phiopt the GIMPLE looks like this:
      if (x_17 < lo_23)
        goto <bb 5>; [50.00%]
      else
        goto <bb 4>; [50.00%]

      <bb 4> [local count: 477815112]:
      _18 = MAX_EXPR <x_17, hi_25>;

      <bb 5>:
      # lo_4 = PHI <x_17(3), lo_23(4)>
      # hi_6 = PHI <hi_25(3), _18(4)>

RTL if-convert can't catch it because the MIN/MAX expressions in the arms use
cmp+csel and so clobber the flags

Reply via email to