[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