https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127897
Bug ID: 127897
Summary: [12/13/14/15/16/17 Regression] x86: set1 vector
constants built with 2-3 instructions instead of a
memory operand
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: mathemagician.ut at gmail dot com
Target Milestone: ---
The generated code is correct, but vector constants of equal elements that
GCC 11 and clang use as a memory operand are now built with extra
instructions.
pr.c:
#include <immintrin.h>
__m128 f(__m128 x) { return _mm_add_ps(_mm_mul_ps(x, _mm_set1_ps(1.5f)),
_mm_set1_ps(0.25f)); }
__m128i g(__m128i x) { return _mm_add_epi32(_mm_mullo_epi32(x,
_mm_set1_epi32(12345)), _mm_set1_epi32(678)); }
$ gcc -O2 -march=x86-64-v2 -S pr.c
GCC 11.5.0 and clang 19.1.7:
f: mulps .LC0(%rip), %xmm0
addps .LC1(%rip), %xmm0
g: pmulld .LC2(%rip), %xmm0
paddd .LC3(%rip), %xmm0
GCC 16.2.0 and trunk (r17-5005):
f: movss .LC1(%rip), %xmm1
shufps $0, %xmm1, %xmm1
mulps %xmm1, %xmm0
movss .LC3(%rip), %xmm1
shufps $0, %xmm1, %xmm1
addps %xmm1, %xmm0
g: movl $12345, %eax
movdqa %xmm0, %xmm1
movd %eax, %xmm0
movl $678, %eax
pshufd $0, %xmm0, %xmm0
pmulld %xmm1, %xmm0
movd %eax, %xmm1
pshufd $0, %xmm1, %xmm1
paddd %xmm1, %xmm0
f is affected since GCC 12, g since GCC 14. Same at -O3 and with any -mtune
tried. With AVX or AVX2, 32-bit integer constants (g, _mm256_set1_epi32) are
built in a general register since GCC 12; clang uses a memory operand or
vpbroadcastd from memory.
-mtune-ctrl=^inter_unit_moves_to_vec restores g but not f.
-mtune-ctrl=^prefer_bcst_from_integer (PR123631) loads g's constants with
movd + pshufd from memory, still two instructions each; f is unchanged.
Caused by (each checked by building cc1 at the revision and its parent):
r12-2463-ga6291d88d5b6c1: ix86_broadcast_from_constant accepts float modes
on any target, so f becomes movss + shufps when there is no AVX.
r14-6534-gbe0ff0866a6f07 (PR112992): removes the TARGET_AVX/TARGET_AVX2
check from ix86_broadcast_from_constant. The commit targets 32-byte
vectors without AVX2, but 16-byte integer vectors are now also built
in a general register with only SSE (g).
r12-1958-gedafb35bdadf30, r12-7530-gb1a741a0304178: the same for integer
vectors with AVX and AVX2.
Known to work: 11.5.0
Known to fail: 12.5.0, 13.3.0, 14.2.0, 15.3.0, 16.2.0, 17.0.0
See also: PR112992, PR123631
Host/Target: x86_64-pc-linux-gnu