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

            Bug ID: 126770
           Summary: inefficient reduction of comparison sum
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rguenth at gcc dot gnu.org
  Target Milestone: ---
            Target: x86_64-*-*

For the tail reduction in PR126028,

        bool test0 = (r2_0 < groupplcutoff2);
        bool test1 = (r2_1 < groupplcutoff2);
        hu += test0 + test1;

we generate awful code with -O3 -march=znver5 which can be seen with the
following reduced testcase (which needs -fno-vect-cost-model):

int foo (double g, double *r, int n)
{
  int hu = 0;
  bool test0 = r[0] < g;
  bool test1 = r[1] < g;
  hu += test0 + test1;
  return hu;
}

we generate

foo:
.LFB0:
        .cfi_startproc
        vmovupd (%rdi), %xmm1
        vmovddup        %xmm0, %xmm0
        movl    $1, %eax
        vcmppd  $1, %xmm0, %xmm1, %k1
        vpbroadcastq    %rax, %xmm0{%k1}{z}
        vpmovqd %xmm0, %xmm0
        vmovd   %xmm0, %eax
        vpextrd $1, %xmm0, %edx
        addl    %edx, %eax

which is in .optimized

  _17 = {g_8(D), g_8(D)};
  vect__1.5_16 = MEM <vector(2) double> [(double *)r_7(D)];
  mask_test0_9.6_18 = vect__1.5_16 < _17;
  vect_patt_11.7_19 = .VCOND_MASK (mask_test0_9.6_18, { 1, 1 }, { 0, 0 });
  vect_patt_12.8_20 = (vector(2) int) vect_patt_11.7_19;
  _22 = BIT_FIELD_REF <vect_patt_12.8_20, 32, 0>;
  _23 = BIT_FIELD_REF <vect_patt_12.8_20, 32, 32>;
  _24 = _22 + _23;

on a high-level the reduction of the mask as 1/0 could be matched as
population count.  But on a low-level STV could have figured that
doing the addl in SSE and the SSE->GPR move only once should be prefered
and similar the movl $1,%eax; vpbroadcastq %rax, %xmm0{%k1}{z}
sequence looks like there must be a more optimal form, not to name
the vpmovqd.

I realize most of this should probably happen on the GIMPLE level.

The first mistake is from the vectorizer and the bool pattern recognition of

  _1 = *r_7(D);
  test0_9 = _1 < g_8(D);
  _2 = MEM[(double *)r_7(D) + 8B];
  test1_10 = _2 < g_8(D);
  _3 = (int) test0_9;
  _4 = (int) test1_10;

where it choses a COND_EXPR with a unsigned long.  I'll open a separate PR
for that.

Reply via email to