Skip to content

Unnecessary conversion of (a==v)&(b==v) into (a!=v)|(b!=v) results in more assembly #116977

@dzaima

Description

@dzaima

The code:

#include <immintrin.h>
_Bool both_equal(__m256i a, __m256i b, __m256i v) {
  __m256i a1 = _mm256_cmpeq_epi8(v, a);
  __m256i b1 = _mm256_cmpeq_epi8(v, b);
  __m256i all = _mm256_and_si256(a1, b1);
  return _mm256_movemask_epi8(all) == 0xFFFFFFFF;
}

compiled with -O3 -march=haswell on clang 19.1 or trunk gives:

both_equal:
        vpcmpeqb        ymm0, ymm2, ymm0
        vpcmpeqd        ymm3, ymm3, ymm3
        vpxor   ymm0, ymm0, ymm3
        vpcmpeqb        ymm1, ymm2, ymm1
        vpxor   ymm1, ymm1, ymm3
        vpor    ymm0, ymm0, ymm1
        vpmovmskb       eax, ymm0
        test    eax, eax
        sete    al
        vzeroupper
        ret

whereas 18.1 produced the better:

both_equal:
        vpxor   ymm0, ymm0, ymm2
        vpxor   ymm1, ymm1, ymm2
        vpor    ymm0, ymm0, ymm1
        vptest  ymm0, ymm0
        sete    al
        vzeroupper
        ret

https://godbolt.org/z/coK5qqErr (variant with 4 tests instead of 2: https://godbolt.org/z/96eEK439G)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions