[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.