https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92436
Bug ID: 92436 Summary: SIMD integer subtract with constant always becomes add Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: zingaburga+gcc at hotmail dot com Target Milestone: --- Firstly, this isn't a bug, rather a missed optimization opportunity (I presume this is the place to post these?). With the optimizer enabled, it seems like SIMD integer subtract, with a constant, always gets turned into a SIMD integer add with the constant negated. For a target like x86 SSE, I suppose this may make sense, as the commutative property of addition gives more flexibility around register placement, but it isn't always beneficial - for example, if the constant could be re-used elsewhere. Example (x86): _mm_or_si128( _mm_sub_epi8(a, _mm_set1_epi8(99)), _mm_set1_epi8(99) ); In this case, the '99' constant can be used in both the subtract and or, but GCC will always convert the first use to a '-99' constant, meaning that it now has to deal with two constants: https://godbolt.org/z/gaKAkA This can have a greater effect when the constants are held in registers, as the negated constant wastes a register, which can sometimes cause otherwise unnecessary register spilling elsewhere. The behavior persists with AVX enabled, and I've even seen it for ARM NEON: https://godbolt.org/z/z3b5mq --- Perhaps a different issue, but maybe related: I noticed that switching the order of the arguments for subtract, GCC seems to think the two constants are different, even though this is not the case: https://godbolt.org/z/6fGhGd For this second example ((99-a)|99), I'd have thought the more appropriate assembly to be something like: vmovdqa xmm1, XMMWORD PTR .LC0[rip] vpsubb xmm0, xmm1, xmm0 vpor xmm0, xmm0, xmm1