[PATCH v3 0/2] arm: recognize vdupq idioms [PR124043]

Richard Earnshaw via Sourceware Forge <[email protected]> Mon, 03 Aug 2026 13:38:45 +0000
Newsgroups gmane.comp.gcc.patches
Message-ID <bmm.hl00t28das.gcc.gcc.rearnsha.208.3.0@forge-stage.sourceware.org>
Hi gcc-patches mailing list,
Richard Earnshaw via Sourceware Forge <[email protected]> has requested that the following forgejo pull request
be published on the mailing list.

Created on: 2026-07-30 15:40:01+00:00
Latest update: 2026-08-03 13:38:45+00:00
Changes: 8 changed files, 314 additions, 74 deletions
Head revision: rearnsha/gcc ref vdupq commit 5f1f4582e0363209ef9b94775fa006ab0f6beebf
Base revision: gcc/gcc ref trunk commit 3db020600d47180dc097f405d1dd7cfcafe24d43 r17-2898-g3db020600d4718
Merge base: 3db020600d47180dc097f405d1dd7cfcafe24d43
Full diff url: https://forge.sourceware.org/gcc/gcc/pulls/208.diff
Discussion:  https://forge.sourceware.org/gcc/gcc/pulls/208
Requested Reviewers: azoff

Changes since v1:
- address comments from Christophe and Torbjorn
- Handle core regs to HF and BF vector modes
- Disambiguate the pattern names


Changed files:
- M: gcc/config/arm/neon.md
- M: gcc/config/arm/vfp.md
- M: gcc/testsuite/gcc.target/arm/armv8_2-fp16-neon-1.c
- M: gcc/testsuite/gcc.target/arm/armv8_2-fp16-neon-2.c
- M: gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c
- M: gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c
- M: gcc/testsuite/gcc.target/arm/crypto-vsha1mq_u32.c
- M: gcc/testsuite/gcc.target/arm/crypto-vsha1pq_u32.c


Richard Earnshaw (2):
  arm: handle neon vec_dup from select of 128-bit vector
  arm: Thumb2 reg preferencing for vfp variant of movsi [PR124043]

 gcc/config/arm/neon.md                        | 164 ++++++++++++++----
 gcc/config/arm/vfp.md                         |   8 +-
 .../gcc.target/arm/armv8_2-fp16-neon-1.c      | 114 +++++++++---
 .../gcc.target/arm/armv8_2-fp16-neon-2.c      |  90 +++++++++-
 .../gcc.target/arm/crypto-vsha1cq_u32.c       |   3 +-
 .../gcc.target/arm/crypto-vsha1h_u32.c        |   3 +-
 .../gcc.target/arm/crypto-vsha1mq_u32.c       |   3 +-
 .../gcc.target/arm/crypto-vsha1pq_u32.c       |   3 +-
 8 files changed, 314 insertions(+), 74 deletions(-)

Range-diff against v2:
1:  117d454d98ccc = 1:  b70a0bc7a64f5 arm: handle neon vec_dup from select of 128-bit vector
2:  ce89660a99eed ! 2:  5f1f4582e0363 arm: Thumb2 reg preferencing for vfp variant of movsi [PR124043]
    @@ Commit message
                 * gcc.target/arm/crypto-vsha1h_u32.c: Likewise.
                 * gcc.target/arm/crypto-vsha1mq_u32.c: Likewise.
                 * gcc.target/arm/crypto-vsha1pq_u32.c: Likewise.
    +            * gcc.target/arm/armv8_2-fp16-neon-1.c: Adjust expected output.
    +            * gcc.target/arm/armv8_2-fp16-neon-2.c: Likewise.
     
      ## gcc/config/arm/vfp.md ##
     @@
    @@ gcc/config/arm/vfp.md
         && (   s_register_operand (operands[0], SImode)
             || s_register_operand (operands[1], SImode))"
     
    + ## gcc/testsuite/gcc.target/arm/armv8_2-fp16-neon-1.c ##
    +@@
    + /* { dg-require-effective-target arm_v8_2a_fp16_neon_ok }  */
    + /* { dg-options "-O2" }  */
    + /* { dg-add-options arm_v8_2a_fp16_neon }  */
    ++/* { dg-final { check-function-bodies "**" "" "" } }  */
    + 
    + /* Test instructions generated for the FP16 vector intrinsics.  */
    + 
    +@@ gcc/testsuite/gcc.target/arm/armv8_2-fp16-neon-1.c: VCVT_N_TEST (vcvt, _u16_f16, uint, float)
    + 
    + VCVT_TEST (vcvta, _s16_f16, int, float)
    + /* { dg-final { scan-assembler-times {vcvta\.s16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvta\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvta\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + VCVT_TEST (vcvta, _u16_f16, uint, float)
    + /* { dg-final { scan-assembler-times {vcvta\.u16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvta\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvta\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + VCVT_TEST (vcvtm, _s16_f16, int, float)
    + /* { dg-final { scan-assembler-times {vcvtm\.s16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvtm\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvtm\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + VCVT_TEST (vcvtm, _u16_f16, uint, float)
    + /* { dg-final { scan-assembler-times {vcvtm\.u16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvtm\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvtm\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + VCVT_TEST (vcvtn, _s16_f16, int, float)
    + /* { dg-final { scan-assembler-times {vcvtn\.s16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvtn\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvtn\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + VCVT_TEST (vcvtn, _u16_f16, uint, float)
    + /* { dg-final { scan-assembler-times {vcvtn\.u16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvtn\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvtn\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + VCVT_TEST (vcvtp, _s16_f16, int, float)
    + /* { dg-final { scan-assembler-times {vcvtp\.s16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvtp\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvtp\.s16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + VCVT_TEST (vcvtp, _u16_f16, uint, float)
    + /* { dg-final { scan-assembler-times {vcvtp\.u16\.f16\td[0-9]+, d[0-9]+} 1 } }
    +-   { dg-final { scan-assembler-times {vcvtp\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }
    +-*/
    ++   { dg-final { scan-assembler-times {vcvtp\.u16\.f16\tq[0-9]+, q[0-9]+} 1 } }  */
    + 
    + UNOP_TEST (vabs)
    + /* { dg-final { scan-assembler-times {vabs\.f16\td[0-9]+, d[0-9]+} 1 } }
    +@@ gcc/testsuite/gcc.target/arm/armv8_2-fp16-neon-1.c: test_vmov_n_f16 (float16_t a)
    + {
    +   return vmov_n_f16 (a);
    + }
    ++/*
    ++** test_vmov_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	(d[0-9]+), r0
    ++**	vmov	r0, r1, \1  @ v4hf
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	d0, \2
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x4_t
    + test_vdup_n_f16 (float16_t a)
    + {
    +   return vdup_n_f16 (a);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\td[0-9]+, r[0-9]+} 2 } }  */
    ++/*
    ++** test_vdup_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	(d[0-9]+), r0
    ++**	vmov	r0, r1, \1  @ v4hf
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	d0, \2
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x8_t
    + test_vmovq_n_f16 (float16_t a)
    + {
    +   return vmovq_n_f16 (a);
    + }
    ++/*
    ++** test_vmovq_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	q[0-9]+, r0
    ++**	vmov	r0, r1, d[0-9]+  @ v8hf
    ++**	vmov	r2, r3, d[0-9]+
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	q0, \1
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x8_t
    + test_vdupq_n_f16 (float16_t a)
    + {
    +   return vdupq_n_f16 (a);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\tq[0-9]+, r[0-9]+} 2 } }  */
    ++/*
    ++** test_vdupq_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	q[0-9]+, r0
    ++**	vmov	r0, r1, d[0-9]+  @ v8hf
    ++**	vmov	r2, r3, d[0-9]+
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	q0, \1
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x4_t
    + test_vdup_lane_f16 (float16x4_t a)
    + {
    +   return vdup_lane_f16 (a, 1);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\td[0-9]+, d[0-9]+\[1\]} 1 } }  */
    ++/*
    ++** test_vdup_lane_f16:
    ++** (
    ++    softfp
    ++**	lsrs?	(r[0-9]+), r0, #16
    ++**	vdup.16	(d[0-9]+), \1
    ++**	vmov	r0, r1, \2  @ v4hf
    ++** |
    ++    hard
    ++**	vdup.16	d0, d0\[1\]
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x8_t
    + test_vdupq_lane_f16 (float16x4_t a)
    + {
    +   return vdupq_lane_f16 (a, 1);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\tq[0-9]+, d[0-9]+\[1\]} 1 } }  */
    ++/*
    ++** test_vdupq_lane_f16:
    ++** (
    ++    softfp
    ++**	lsrs?	(r[0-9]+), r0, #16
    ++**	vdup.16	q[0-9], \1
    ++**	vmov	r0, r1, d[0-9]+  @ v8hf
    ++**	vmov	r2, r3, d[0-9]+
    ++** |
    ++    hard
    ++**	vdup.16	q0, d0\[1\]
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x4_t
    + test_vext_f16 (float16x4_t a, float16x4_t b)
    +
    + ## gcc/testsuite/gcc.target/arm/armv8_2-fp16-neon-2.c ##
    +@@ gcc/testsuite/gcc.target/arm/armv8_2-fp16-neon-2.c: test_vmov_n_f16 (float16_t a)
    + {
    +   return vmov_n_f16 (a);
    + }
    ++/*
    ++** test_vmov_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	(d[0-9]+), r0
    ++**	vmov	r0, r1, \1  @ v4hf
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	d0, \2
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x4_t
    + test_vdup_n_f16 (float16_t a)
    + {
    +   return vdup_n_f16 (a);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\td[0-9]+, r[0-9]+} 3 } }  */
    ++/*
    ++** test_vdup_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	(d[0-9]+), r0
    ++**	vmov	r0, r1, \1  @ v4hf
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	d0, \2
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x8_t
    + test_vmovq_n_f16 (float16_t a)
    + {
    +   return vmovq_n_f16 (a);
    + }
    ++/*
    ++** test_vmovq_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	q[0-9]+, r0
    ++**	vmov	r0, r1, d[0-9]+  @ v8hf
    ++**	vmov	r2, r3, d[0-9]+
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	q0, \1
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x8_t
    + test_vdupq_n_f16 (float16_t a)
    + {
    +   return vdupq_n_f16 (a);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\tq[0-9]+, r[0-9]+} 3 { target arm_hf_eabi } } }  */
    +-/* { dg-final { scan-assembler-times {vdup\.16\tq[0-9]+, r[0-9]+} 2 { target { ! arm_hf_eabi } } } }  */
    ++/*
    ++** test_vdupq_n_f16:
    ++** (
    ++    softfp
    ++**	vdup.16	q[0-9]+, r0
    ++**	vmov	r0, r1, d[0-9]+  @ v8hf
    ++**	vmov	r2, r3, d[0-9]+
    ++** |
    ++    hardfp
    ++    Note: We should be able to do this with 'vdup.16 d0, d[0]'
    ++**	vmov.f16	(r[0-9]+), s0	@ __fp16
    ++**	vdup.16	q0, \1
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x4_t
    + test_vdup_lane_f16 (float16x4_t a)
    + {
    +   return vdup_lane_f16 (a, 1);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\td[0-9]+, d[0-9]+\[1\]} 1 } }  */
    ++/*
    ++** test_vdup_lane_f16:
    ++** (
    ++    softfp
    ++**	lsrs?	(r[0-9]+), r0, #16
    ++**	vdup.16	(d[0-9]+), \1
    ++**	vmov	r0, r1, \2  @ v4hf
    ++** |
    ++    hard
    ++**	vdup.16	d0, d0\[1\]
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x8_t
    + test_vdupq_lane_f16 (float16x4_t a)
    + {
    +   return vdupq_lane_f16 (a, 1);
    + }
    +-/* { dg-final { scan-assembler-times {vdup\.16\tq[0-9]+, d[0-9]+\[1\]} 1 } }  */
    ++/*
    ++** test_vdupq_lane_f16:
    ++** (
    ++    softfp
    ++**	lsrs?	(r[0-9]+), r0, #16
    ++**	vdup.16	q[0-9], \1
    ++**	vmov	r0, r1, d[0-9]+  @ v8hf
    ++**	vmov	r2, r3, d[0-9]+
    ++** |
    ++    hard
    ++**	vdup.16	q0, d0\[1\]
    ++** )
    ++**	bx	lr
    ++*/
    + 
    + float16x4_t
    + test_vext_f16 (float16x4_t a, float16x4_t b)
    +
      ## gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c ##
     @@ gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c: uint32_t foo (void)
      TEST_SHA1C_VEC_SELECT (GET_LANE)
-- 
2.54.0