https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102494
Bug ID: 102494
Summary: Failure to optimize out vector reduction properly
especially when using OpenMP
Product: gcc
Version: 12.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: gabravier at gmail dot com
Target Milestone: ---
#include <stdint.h>
#include <stddef.h>
typedef int8_t simde_int8x8_t __attribute__((__vector_size__(8)));
int16_t
simde_vaddlv_s8(simde_int8x8_t a) {
int16_t r = 0;
#pragma omp simd reduction(+:r)
for (size_t i = 0 ; i < (sizeof(a) / sizeof(a[0])) ; i++) {
r += a[i];
}
return r;
}
Compiled with -O3 -fopenmp-simd, this is the output on AMD64:
simde_vaddlv_s8(signed char __vector(8)):
pxor xmm1, xmm1
movdqa xmm2, xmm0
pcmpgtb xmm1, xmm0
punpcklbw xmm0, xmm1
punpcklbw xmm2, xmm1
pshufd xmm0, xmm0, 78
movq QWORD PTR [rsp-24], xmm2
movq QWORD PTR [rsp-16], xmm0
movdqa xmm0, XMMWORD PTR [rsp-24]
psrldq xmm0, 8
paddw xmm0, XMMWORD PTR [rsp-24]
movdqa xmm1, xmm0
psrldq xmm1, 4
paddw xmm0, xmm1
movdqa xmm1, xmm0
psrldq xmm1, 2
paddw xmm0, xmm1
pextrw eax, xmm0, 0
ret
This is what Clang manages:
simde_vaddlv_s8(signed char __vector(8)):
punpcklbw xmm0, xmm0 # xmm0 =
xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
psraw xmm0, 8
pshufd xmm1, xmm0, 238 # xmm1 = xmm0[2,3,2,3]
paddw xmm1, xmm0
pshufd xmm0, xmm1, 85 # xmm0 = xmm1[1,1,1,1]
paddw xmm0, xmm1
movdqa xmm1, xmm0
psrld xmm1, 16
paddw xmm1, xmm0
movd eax, xmm1
ret
Weirdly enough, removing the `#pragma omp simd reduction(+r)` slightly improves
GCC's output to this:
simde_vaddlv_s8(signed char __vector(8)):
pxor xmm1, xmm1
movdqa xmm2, xmm0
pcmpgtb xmm1, xmm0
punpcklbw xmm0, xmm1
punpcklbw xmm2, xmm1
pshufd xmm0, xmm0, 78
paddw xmm0, xmm2
pextrw edx, xmm0, 1
pextrw eax, xmm0, 0
add eax, edx
pextrw edx, xmm0, 2
add eax, edx
pextrw edx, xmm0, 3
add eax, edx
ret