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

            Bug ID: 127266
           Summary: Missed vector optimization: `(((a ^ b) & C) == 0) | (a
                    != b)` is not folded to all-true
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mikaseianatsu at proton dot me
  Target Milestone: ---

The following lane-wise vector expression is always true, but GCC does not fold
it to an all-true vector mask. The analogous scalar expression is folded to 1.


Testcase:

typedef unsigned long long v4u64 __attribute__((vector_size(32)));
typedef long long v4i64 __attribute__((vector_size(32)));

__attribute__((noipa)) v4i64
f (v4u64 a, v4u64 b)
{
  v4u64 d = a ^ b;
  v4u64 m = d & (v4u64) { 0xabcdULL, 0xabcdULL, 0xabcdULL, 0xabcdULL };
  return (m == (v4u64) { 0, 0, 0, 0 }) | (a != b);
}


The testcase was derived from the scalar pattern in:

  gcc/testsuite/gcc.dg/tree-ssa/pr102793-1.c


Compile with:

  gcc -O2 -mavx2 -fno-tree-vectorize -S \
    -fdump-tree-optimized testcase.c -o testcase.s


Expected result:

For each lane, let d = a ^ b. Since a != b is equivalent to d != 0, the
expression is equivalent to

  ((d & C) == 0) | (d != 0)

If d == 0, the first comparison is true. Otherwise, the second comparison is
true. Therefore every lane is always true, and the result can be folded to an
all-true vector mask:

  return (v4i64) { -1LL, -1LL, -1LL, -1LL };


Current result:

The optimized GIMPLE still retains the full computation:

  d_6 = a_4(D) ^ b_5(D);
  m_7 = d_6 & { 43981, 43981, 43981, 43981 };
  _1 = m_7 == { 0, 0, 0, 0 };
  _2 = a_4(D) != b_5(D);
  _3 = _1 | _2;
  return VIEW_CONVERT_EXPR<v4i64>(_3);

For example, on x86-64 with AVX2, the generated code for f contains eight
vector instructions:

  vpbroadcastq
  vpxor
  vpcmpeqq
  vpand
  vpxor
  vpcmpeqq
  vpcmpeqq
  vpor
  ret

An all-true vector can instead be produced with a single vector instruction:

  vpcmpeqd %ymm0, %ymm0, %ymm0
  ret

This appears to be a missed lane-wise boolean simplification. The equivalent
scalar form is already simplified by GCC.


Compiler:

  Target: x86_64-pc-linux-gnu
  Configure options: --enable-languages=c,c++ --disable-bootstrap
--disable-multilib --enable-checking=release
  gcc version 17.0.0 20260827 (experimental) (GCC)
  GCC source: g:d38b7b3
  • [Bug tree-optimization/127266]... mikaseianatsu at proton dot me via Gcc-bugs

Reply via email to