https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120027
--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Kyrylo Tkachov <[email protected]>: https://gcc.gnu.org/g:395e3d8131c189cd58e8c8061cdc77d1c44e3822 commit r17-2112-g395e3d8131c189cd58e8c8061cdc77d1c44e3822 Author: Kyrylo Tkachov <[email protected]> Date: Sun Jun 28 10:48:28 2026 -0700 aarch64: Fold merging svextb/svexth/svextw with a ptrue to AND [PR120027] For unsigned types the svextb, svexth and svextw intrinsics are plain zero-extends, which the expander already lowers to a bitwise AND with a constant mask. The any/don't-care (_x) form and the zeroing (_z) form with an all-true predicate therefore compile to a single unpredicated AND, but the merging (_m) form with an all-true predicate did not: it kept the inactive argument and produced a predicated UXT. For example svuint64_t f (svuint64_t x, svuint64_t y) { return svextb_m (y, svptrue_b64 (), x); } compiled to ptrue p3.b, all mov z31.d, z0.d movprfx z0, z1 uxtb z0.d, p3/m, z31.d ret where a single and z0.d, z0.d, #0xff ret is sufficient, because the all-true predicate makes the inactive operand dead. Give svext_bhw_impl a gimple fold that rewrites the unsigned merging form with an all-true predicate to a BIT_AND_EXPR. Signed types (which use a real sign-extend instruction), partial predicates and pfalse predicates are left to the existing handling, as is the _x form, which the expander already turns into an AND. Bootstrapped and tested on aarch64-none-linux-gnu. PR target/120027 gcc/ChangeLog: * config/aarch64/aarch64-sve-builtins-base.cc (svext_bhw_impl::fold): New member function. Fold the unsigned svextb/svexth/svextw intrinsics to a bitwise AND when the merging form has an all-true predicate. gcc/testsuite/ChangeLog: * gcc.target/aarch64/sve/acle/general/pr120027.c: New test. Signed-off-by: Kyrylo Tkachov <[email protected]>
