https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111609
--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The trunk branch has been updated by Richard Earnshaw <[email protected]>: https://gcc.gnu.org/g:93ac5163b5d02c2dfde88c3ec7b1f366caab9b45 commit r17-3926-g93ac5163b5d02c2dfde88c3ec7b1f366caab9b45 Author: Dominic P <[email protected]> Date: Sun Aug 2 11:56:05 2026 +0100 arm: fix vshll_n intrinsics with boundary shift [PR111609] The NEON widening-shift-left-long intrinsics (vshll_n_s8/s16/s32 and vshll_n_u8/u16/u32) accept a shift amount in the range [0, element_size]. The bounds check in neon_vshll<sup>_n<mode> already permits a shift of zero (its stale comment said "0 < imm" while the code implements "0 <= imm"), but it then emitted a literal "vshll.<sz> qD, dN, #0". The VSHLL encoding cannot represent a shift of zero -- valid immediates are 1..element_size -- so the assembler rejected the output with "Error: immediate value out of range". The ACLE semantics of a widening shift-left by zero are exactly those of a widening move, so divert the imm == 0 case to VMOVL, which is the correct and encodable instruction. This turns previously-broken valid ACLE code into working code (better QoI than rejecting it). Nonzero shifts, including a shift by the element size, are unchanged. A related issue exists when the shift size is equal to the element size. For these cases the mnemonic should use a signless form (i8, i16, i32). Assisted-by: Claude Opus 5 (Anthropic) PR target/111609 gcc/ChangeLog: * config/arm/neon.md (neon_vshll<sup>_n<mode>): Emit vmovl for a shift of zero. Use signless form when the shift amount == element size. gcc/testsuite/ChangeLog: * gcc.target/arm/pr111609.c: New test. Signed-off-by: Dominic P <[email protected]> Co-authored-by: Richard Earnshaw <[email protected]>
