[PATCH v2 0/2] arm: recognize vdupq idioms [PR124043]
Richard Earnshaw via Sourceware Forge <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <bmm.hkwtqyput0.gcc.gcc.rearnsha.208.2.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-07-31 16:04:30+00:00 Changes: 6 changed files, 135 additions, 49 deletions Head revision: rearnsha/gcc ref vdupq commit ce89660a99eedb891437c537b4f98f2b95aed94e Base revision: gcc/gcc ref trunk commit b90df55625eb40b05e0628097765d0a2cb368ced r17-2853-gb90df55625eb40 Merge base: b90df55625eb40b05e0628097765d0a2cb368ced 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/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/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 +- 6 files changed, 135 insertions(+), 49 deletions(-) Range-diff against v1: 1: abeec128d7b6 ! 1: 117d454d98cc arm: handle neon vec_dup from select of 128-bit vector @@ Commit message some cases we can use the core reg directly (when no shift is needed) since the upper bits are ignored. + I've also disambiguated the two paterns named + neon_vdup_lane<mode>_internal by inserting the iterator name into the + pattern. This doesn't change anything in terms of generated code, but + makes the pattern names in the MD file unique. + gcc/ChangeLog: - * config/arm/neon.md (neon_vdup_lane<mode>_internal): Handle - core registers as the input vector operand by splitting. - (neon_vdupq_lane<mode>_internal): New pattern + * config/arm/neon.md (neon_vdup_lane<VDQW:mode>_internal): + Handle core registers as the input vector operand by splitting. + (neon_vdup_lane<VHFBF:mode>_internal): Likewise. + (neon_vdupq_lane<VQ2BF:mode>_internal): New pattern. gcc/testsuite/ChangeLog: @@ gcc/config/arm/neon.md: if (BYTES_BIG_ENDIAN) - (vec_select:<V_elem> - (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w") - (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] -+(define_insn_and_split "neon_vdup_lane<mode>_internal" ++(define_insn_and_split "neon_vdup_lane<VDQW:mode>_internal" + [(set (match_operand:VDQW 0 "s_register_operand" "=w,w") + (vec_duplicate:VDQW + (vec_select:<V_elem> @@ gcc/config/arm/neon.md: if (BYTES_BIG_ENDIAN) + } + [(set_attr "length" "4,8") + (set_attr "type" "neon_dup<q>")] -+) -+ + ) + +-(define_insn "neon_vdup_lane<mode>_internal" +- [(set (match_operand:VHFBF 0 "s_register_operand" "=w") +- (vec_duplicate:VHFBF +- (vec_select:<V_elem> +- (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w") +- (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] +- "TARGET_NEON && (TARGET_FP16 || TARGET_BF16_SIMD)" +-{ +- if (BYTES_BIG_ENDIAN) +- { +- int elt = INTVAL (operands[2]); +; There isn't an intrinsic for this, but the compiler can generate it +; idomatically from other operations. -+(define_insn_and_split "neon_vdupq_lane<mode>_internal" ++(define_insn_and_split "neon_vdupq_lane<VQ2BF:mode>_internal" + [(set (match_operand:VQ2BF 0 "s_register_operand" "=w,w") + (vec_duplicate:VQ2BF + (vec_select:<V_elem> @@ gcc/config/arm/neon.md: if (BYTES_BIG_ENDIAN) + (clobber (match_scratch:<V_elem> 3 "=X,r"))] + "TARGET_NEON" + "#" -+ "" ;; && reload_completed" ++ "" + [(parallel + [(set (match_dup 0) + (vec_duplicate:VQ2BF @@ gcc/config/arm/neon.md: if (BYTES_BIG_ENDIAN) + } + [(set_attr "type" "neon_dup<q>") + (set_attr "length" "4,8")] ++) ++ ++(define_insn_and_split "neon_vdup_lane<VHFBF:mode>_internal" ++ [(set (match_operand:VHFBF 0 "s_register_operand" "=w,w") ++ (vec_duplicate:VHFBF ++ (vec_select:<V_elem> ++ (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w,r") ++ (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))) ++ (clobber (match_scratch:<V_elem> 3 "=X,r"))] ++ "TARGET_NEON && (TARGET_FP16 || TARGET_BF16_SIMD)" ++ { ++ if (BYTES_BIG_ENDIAN) ++ { ++ int elt = INTVAL (operands[2]); ++ elt = GET_MODE_NUNITS (<V_double_vector_mode>mode) - 1 - elt; ++ operands[2] = GEN_INT (elt); ++ } ++ if (<Is_d_reg>) ++ return "vdup.<V_sz_elem>\t%P0, %P1[%c2]"; ++ else ++ return "vdup.<V_sz_elem>\t%q0, %P1[%c2]"; ++ } ++ "&& REGNO (operands[1]) <= LAST_ARM_REGNUM" ++ [(set (match_dup 0) ++ (vec_duplicate:VHFBF (match_dup 3)))] ++ { ++ unsigned HOST_WIDE_INT elt = UINTVAL (operands[2]); ++ if (BYTES_BIG_ENDIAN) + elt = GET_MODE_NUNITS (<V_double_vector_mode>mode) - 1 - elt; +- operands[2] = GEN_INT (elt); +- } +- if (<Is_d_reg>) +- return "vdup.<V_sz_elem>\t%P0, %P1[%c2]"; +- else +- return "vdup.<V_sz_elem>\t%q0, %P1[%c2]"; +-} +- [(set_attr "type" "neon_dup<q>")] ++ unsigned HOST_WIDE_INT size = GET_MODE_SIZE (<V_elem>mode); ++ int base_regno = REGNO (operands[1]); ++ int regno = (base_regno ++ + subreg_regno_offset (base_regno, <V_double_vector_mode>mode, ++ elt * size, SImode)); ++ unsigned HOST_WIDE_INT offset = (elt * size) % GET_MODE_SIZE (SImode); ++ if (offset != 0) ++ { ++ gcc_assert (offset < 4); ++ rtx reg = gen_rtx_REG (SImode, regno); ++ rtx shift = gen_rtx_LSHIFTRT (SImode, reg, ++ GEN_INT (offset * BITS_PER_UNIT)); ++ emit_move_insn (gen_rtx_SUBREG (SImode, operands[3], 0), ++ shift); ++ } ++ else ++ operands[3] = gen_rtx_REG (<V_elem>mode, regno); ++ } ++ [(set_attr "length" "4,8") ++ (set_attr "type" "neon_dup<q>")] ) - (define_insn "neon_vdup_lane<mode>_internal" + (define_expand "neon_vdup_lane<mode>" ## gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c ## @@ gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c: TEST_SHA1C_VEC_SELECT (GET_LANE) @@ gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c: TEST_SHA1C_VEC_SELECT (GET_LA /* { dg-final { scan-assembler-times {sha1c.32\tq[0-9]+, q[0-9]+} 5 } } */ /* { dg-final { scan-assembler-times {vdup.32\tq[0-9]+, (?:r[0-9]+|d[0-9]+\[[0-9]+\])} 4 { xfail { arm_thumb2 && arm_hf_eabi } } } } */ -/* { dg-final { scan-assembler-times {vmov.32\tr[0-9]+, d[0-9]+\[[0-9]+\]} 3 } } */ -+ ## gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c ## @@ gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c: TEST_SHA1H_VEC_SELECT (GET_LANE) 2: 3b9cc3468af3 ! 2: ce89660a99ee arm: Thumb2 reg preferencing for vfp variant of movsi [PR124043] @@ gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c: uint32_t foo (void) /* { dg-final { scan-assembler-times {sha1c.32\tq[0-9]+, q[0-9]+} 5 } } */ -/* { dg-final { scan-assembler-times {vdup.32\tq[0-9]+, (?:r[0-9]+|d[0-9]+\[[0-9]+\])} 4 { xfail { arm_thumb2 && arm_hf_eabi } } } } */ -- +/* { dg-final { scan-assembler-times {vdup.32\tq[0-9]+, (?:r[0-9]+|d[0-9]+\[[0-9]+\])} 4 } } */ ## gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c ## -- 2.54.0