]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AArch64: Annotate SVE instructions with new instruction attribute.
authorJennifer Schmitz <jschmitz@nvidia.com>
Fri, 11 Jul 2025 13:07:30 +0000 (06:07 -0700)
committerJennifer Schmitz <jschmitz@nvidia.com>
Wed, 24 Sep 2025 14:18:17 +0000 (16:18 +0200)
In this patch, we add the new instruction attribute "sve_type" and use it to
annotate the SVE instructions in aarch64-sve.md and aarch64-sve2.md. This
allows us to use instruction attributes to group instructions into dispatch
groups for dispatch scheduling. While there had already been fine-grained
annotation of scalar and neon instructions (mostly using the "type"-attribute),
annotation was missing for SVE instructions.

The values of the attribute "sve_type" are comparatively coarse-grained, but
fulfill the two criteria we aimed for with regard to dispatch scheduling:
- the annotation allows the definition of CPU-specific high-level attributes
  mapping instructions to dispatch constraints
- the annotation is by itself CPU-independent and consistent, i.e. all
  instructions fulfilling certain criteria are tagged with the corresponding
  value

The patch was bootstrapped and tested on aarch64-linux-gnu, no regression.

Signed-off-by: Jennifer Schmitz <jschmitz@nvidia.com>
gcc/ChangeLog:

* config/aarch64/aarch64-sve.md: Annotate instructions with
attribute sve_type.
* config/aarch64/aarch64-sve2.md: Likewise.
* config/aarch64/aarch64.md (sve_type): New attribute sve_type.
* config/aarch64/iterators.md (sve_type_unspec): New int attribute.
(sve_type_int): New code attribute.
(sve_type_fp): New int attribute.

gcc/config/aarch64/aarch64-sve.md
gcc/config/aarch64/aarch64-sve2.md
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md

index 1ebcffe88a32c4748eb3208113803fdb32984bb0..8c47d441c3fd6a70f0d2ef5a26883733a9fd36c1 100644 (file)
    && ((lra_in_progress || reload_completed)
        || (register_operand (operands[0], <MODE>mode)
           && nonmemory_operand (operands[1], <MODE>mode)))"
-  {@ [ cons: =0 , 1    ]
-     [ w        , Utr  ] ldr\t%0, %1
-     [ Utr      , w    ] str\t%1, %0
-     [ w        , w    ] mov\t%0.d, %1.d
-     [ w        , Dn   ] << aarch64_output_sve_mov_immediate (operands[1]);
+  {@ [ cons: =0 , 1   ; attrs: sve_type ]
+     [ w        , Utr ; sve_load_1reg   ] ldr\t%0, %1
+     [ Utr      , w   ; sve_store_1reg  ] str\t%1, %0
+     [ w        , w   ; *               ] mov\t%0.d, %1.d
+     [ w        , Dn  ; *               ] << aarch64_output_sve_mov_immediate (operands[1]);
   }
 )
 
   "#"
   "&& 1"
   [(set (match_dup 0)
-       (match_dup 2))])
+       (match_dup 2))]
+  {}
+  [(set_attr "sve_type" "sve_load_1reg,sve_store_1reg")]
+)
 
 ;; Unpredicated moves that cannot use LDR and STR, i.e. partial vectors
 ;; or vectors for which little-endian ordering isn't acceptable.  Memory
   "TARGET_SVE
    && (register_operand (operands[0], <MODE>mode)
        || register_operand (operands[2], <MODE>mode))"
-  {@ [ cons: =0 , 1   , 2  ]
-     [ w        , Upl , w  ] #
-     [ w        , Upl , m  ] ld1<Vesize>\t%0.<Vctype>, %1/z, %2
-     [ m        , Upl , w  ] st1<Vesize>\t%2.<Vctype>, %1, %0
+  {@ [ cons: =0 , 1   , 2 ; attrs: sve_type ]
+     [ w        , Upl , w ; *               ] #
+     [ w        , Upl , m ; sve_load_1reg   ] ld1<Vesize>\t%0.<Vctype>, %1/z, %2
+     [ m        , Upl , w ; sve_store_1reg  ] st1<Vesize>\t%2.<Vctype>, %1, %0
   }
   "&& register_operand (operands[0], <MODE>mode)
    && register_operand (operands[2], <MODE>mode)"
   "TARGET_SVE
    && (register_operand (operands[0], <MODE>mode)
        || register_operand (operands[1], <MODE>mode))"
-  {@ [ cons: =0 , 1    ]
-     [ Upa      , Upa  ] mov\t%0.b, %1.b
-     [ m        , Upa  ] str\t%1, %0
-     [ Upa      , m    ] ldr\t%0, %1
-     [ Upa      , Dn   ] << aarch64_output_sve_mov_immediate (operands[1]);
+  {@ [ cons: =0 , 1   ; attrs: sve_type ]
+     [ Upa      , Upa ; sve_pred_misc   ] mov\t%0.b, %1.b
+     [ m        , Upa ; sve_store_pred  ] str\t%1, %0
+     [ Upa      , m   ; sve_load_pred   ] ldr\t%0, %1
+     [ Upa      , Dn  ; sve_pred_misc   ] << aarch64_output_sve_mov_immediate (operands[1]);
   }
 )
 
   {
     operands[2] = operands[3] = CONSTM1_RTX (VNx16BImode);
   }
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; Match PTRUES Pn.[HSD] when both the predicate and flags are useful.
     operands[2] = CONSTM1_RTX (VNx16BImode);
     operands[3] = CONSTM1_RTX (<MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; Match PTRUES Pn.B when only the flags result is useful (which is
   {
     operands[2] = operands[3] = CONSTM1_RTX (VNx16BImode);
   }
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; Match PTRUES Pn.[HWD] when only the flags result is useful (which is
     operands[2] = CONSTM1_RTX (VNx16BImode);
     operands[3] = CONSTM1_RTX (<MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; -------------------------------------------------------------------------
      [ Dm      ] setffr
      [ Upa     ] wrffr\t%0.b
   }
+  [(set_attr "sve_type" "sve_ffr")]
 )
 
 ;; [L2 in the block comment above about FFR handling]
        (reg:VNx16BI FFRT_REGNUM))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "rdffr\t%0.b"
+  [(set_attr "sve_type" "sve_ffr")]
 )
 
 ;; Likewise with zero predication.
      [ ?Upa    , 0Upa; yes                 ] ^
      [ Upa     , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_ffr")]
 )
 
 ;; Read the FFR to test for a fault, without using the predicate result.
      [ ?Upa    , 0Upa; yes                 ] ^
      [ Upa     , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_ffr")]
 )
 
 ;; Same for unpredicated RDFFR when tested with a known PTRUE.
      [ ?Upa    , 0Upa; yes                 ] ^
      [ Upa     , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_ffr")]
 )
 
 ;; Read the FFR with zero predication and test the result.
      [ ?Upa    , 0Upa; yes                 ] ^
      [ Upa     , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_ffr")]
 )
 
 ;; Same for unpredicated RDFFR when tested with a known PTRUE.
      [ ?Upa    , 0Upa; yes                 ] ^
      [ Upa     , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_ffr")]
 )
 
 ;; [R3 in the block comment above about FFR handling]
          UNSPEC_LD1_SVE))]
   "TARGET_SVE"
   "ld1<Vesize>\t%0.<Vctype>, %2/z, %1"
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; Unpredicated LD[234].
          UNSPEC_LDN))]
   "TARGET_SVE"
   "ld<vector_count><Vesize>\t%0, %2/z, %1"
+  [(set_attr "sve_type" "sve_load_<vector_count>reg")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[3] = CONSTM1_RTX (<SVE_HSDI:VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; Same as above without the maskload_else_operand to still allow combine to
   {
     operands[3] = CONSTM1_RTX (<SVE_HSDI:VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE_LDFF1_LDNF1))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "ld<fn>f1<Vesize>\t%0.<Vetype>, %2/z, %1"
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[3] = CONSTM1_RTX (<SVE_HSDI:VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_LDNT1_SVE))]
   "TARGET_SVE"
   "ldnt1<Vesize>\t%0.<Vetype>, %2/z, %1"
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
      [&w, rk,         w, Ui1, i,   Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw %p4]
      [?w, rk,         0, Ui1, i,   Upl] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_32")]
 )
 
 ;; Predicated gather loads for 64-bit elements.  The value of operand 3
      [&w, rk,         w, i, i,   Upl] ld1<Vesize>\t%0.d, %5/z, [%1, %2.d, lsl %p4]
      [?w, rk,         0, i, i,   Upl] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being extended from 32 bits.
   {
     operands[6] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being truncated to 32 bits and then
   {
     operands[6] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being truncated to 32 bits and then
      [&w, rk, w, i, i,   Upl ] ld1<Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw %p4]
      [?w, rk, 0, i, i,   Upl ] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[6] = CONSTM1_RTX (VNx4BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_32")]
 )
 
 ;; Predicated extending gather loads for 64-bit elements.  The value of
   {
     operands[6] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being extended from 32 bits.
     operands[6] = CONSTM1_RTX (VNx2BImode);
     operands[7] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being truncated to 32 bits and then
     operands[6] = CONSTM1_RTX (VNx2BImode);
     operands[7] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being truncated to 32 bits and then
   {
     operands[7] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; -------------------------------------------------------------------------
      [&w, rk,  w, Ui1, i,   Upl] ldff1w\t%0.s, %5/z, [%1, %2.s, uxtw %p4]
      [?w, rk,  0, Ui1, i,   Upl] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_32")]
 )
 
 ;; Predicated first-faulting gather loads for 64-bit elements.  The value
      [&w, rk,  w, i, i,   Upl ] ldff1d\t%0.d, %5/z, [%1, %2.d, lsl %p4]
      [?w, rk,  0, i, i,   Upl ] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being sign-extended from 32 bits.
   {
     operands[6] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being zero-extended from 32 bits.
      [&w, rk, w, i, i,   Upl ] ldff1d\t%0.d, %5/z, [%1, %2.d, uxtw %p4]
      [?w, rk, 0, i, i,   Upl ] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[6] = CONSTM1_RTX (VNx4BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_32")]
 )
 
 ;; Predicated extending first-faulting gather loads for 64-bit elements.
   {
     operands[6] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being sign-extended from 32 bits.
     operands[6] = CONSTM1_RTX (VNx2BImode);
     operands[7] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Likewise, but with the offset being zero-extended from 32 bits.
   {
     operands[7] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; =========================================================================
          UNSPEC_ST1_SVE))]
   "TARGET_SVE"
   "st1<Vesize>\t%1.<Vctype>, %2, %0"
+  [(set_attr "sve_type" "sve_store_1reg")]
 )
 
 ;; Unpredicated ST[234].  This is always a full update, so the dependence
          UNSPEC_STN))]
   "TARGET_SVE"
   "st<vector_count><Vesize>\t%1, %2, %0"
+  [(set_attr "sve_type" "sve_store_<vector_count>reg")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_ST1_SVE))]
   "TARGET_SVE"
   "st1<VNx8_NARROW:Vesize>\t%1.<VNx8_WIDE:Vetype>, %2, %0"
+  [(set_attr "sve_type" "sve_store_1reg")]
 )
 
 ;; Predicated truncate and store, with 4 elements per 128-bit block.
          UNSPEC_ST1_SVE))]
   "TARGET_SVE"
   "st1<VNx4_NARROW:Vesize>\t%1.<VNx4_WIDE:Vetype>, %2, %0"
+  [(set_attr "sve_type" "sve_store_1reg")]
 )
 
 ;; Predicated truncate and store, with 2 elements per 128-bit block.
          UNSPEC_ST1_SVE))]
   "TARGET_SVE"
   "st1<VNx2_NARROW:Vesize>\t%1.<VNx2_WIDE:Vetype>, %2, %0"
+  [(set_attr "sve_type" "sve_store_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_STNT1_SVE))]
   "TARGET_SVE"
   "stnt1<Vesize>\t%1.<Vetype>, %2, %0"
+  [(set_attr "sve_type" "sve_store_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
      [ rk         , w , Z   , i   , w , Upl  ] st1<Vesize>\t%4.s, %5, [%0, %1.s, sxtw %p3]
      [ rk         , w , Ui1 , i   , w , Upl  ] st1<Vesize>\t%4.s, %5, [%0, %1.s, uxtw %p3]
   }
+  [(set_attr "sve_type" "sve_scatterstore_32")]
 )
 
 ;; Predicated scatter stores for 64-bit elements.  The value of operand 2
      [ rk         , w , Ui1 , w , Upl  ] st1<Vesize>\t%4.d, %5, [%0, %1.d]
      [ rk         , w , i   , w , Upl  ] st1<Vesize>\t%4.d, %5, [%0, %1.d, lsl %p3]
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; Likewise, but with the offset being extended from 32 bits.
   {
     operands[6] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; Likewise, but with the offset being truncated to 32 bits and then
   {
     operands[6] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; Likewise, but with the offset being truncated to 32 bits and then
      [ rk      , w , Ui1 , w , Upl  ] st1<Vesize>\t%4.d, %5, [%0, %1.d, uxtw]
      [ rk      , w , i   , w , Upl  ] st1<Vesize>\t%4.d, %5, [%0, %1.d, uxtw %p3]
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w       , Z   , w , Upl  ] st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, sxtw %p3]
      [ w       , Ui1 , w , Upl  ] st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, uxtw %p3]
   }
+  [(set_attr "sve_type" "sve_scatterstore_32")]
 )
 
 ;; Predicated truncating scatter stores for 64-bit elements.  The value of
      [ w       , w , Upl  ] st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d]
      [ w       , w , Upl  ] st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, lsl %p3]
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; Likewise, but with the offset being sign-extended from 32 bits.
   {
     operands[6] = copy_rtx (operands[5]);
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; Likewise, but with the offset being zero-extended from 32 bits.
      [ rk      , w , w , Upl  ] st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, uxtw]
      [ rk      , w , w , Upl  ] st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, uxtw %p3]
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; =========================================================================
     emit_insn (gen_aarch64_sve_ld1rq<mode> (operands[0], operands[1], gp));
     DONE;
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Duplicate an Advanced SIMD vector to fill an SVE vector (BE version).
     operands[1] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
     return "dup\t%0.q, %1.q[0]";
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; This is used for vec_duplicate<mode>s from memory, but can also
          UNSPEC_SEL))]
   "TARGET_SVE"
   "ld1r<Vesize>\t%0.<Vetype>, %1/z, %2"
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; Load 128 bits from memory under predicate control and duplicate to
     operands[1] = gen_rtx_MEM (<VEL>mode, XEXP (operands[1], 0));
     return "ld1rq<Vesize>\t%0.<Vetype>, %2/z, %1";
   }
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 (define_insn "@aarch64_sve_ld1ro<mode>"
     operands[1] = gen_rtx_MEM (<VEL>mode, XEXP (operands[1], 0));
     return "ld1ro<Vesize>\t%0.<Vetype>, %2/z, %1";
   }
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ??&w     , w , rZ ; yes            ] movprfx\t%0, %1\;insr\t%0.<Vetype>, %<vwcore>2
      [ ?&w      , w , w  ; yes            ] movprfx\t%0, %1\;insr\t%0.<Vetype>, %<Vetype>2
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:<VEL> 1 "aarch64_sve_index_operand")
          (match_operand:<VEL> 2 "aarch64_sve_index_operand")))]
   "TARGET_SVE"
-  {@ [ cons: =0 , 1   , 2    ]
-     [ w        , Usi , r    ] index\t%0.<Vctype>, #%1, %<vccore>2
-     [ w        , r   , Usi  ] index\t%0.<Vctype>, %<vccore>1, #%2
-     [ w        , r   , r    ] index\t%0.<Vctype>, %<vccore>1, %<vccore>2
+  {@ [ cons: =0 , 1   , 2   ; attrs: sve_type   ]
+     [ w        , Usi , r   ; sve_int_index     ] index\t%0.<Vctype>, #%1, %<vccore>2
+     [ w        , r   , Usi ; sve_int_index     ] index\t%0.<Vctype>, %<vccore>1, #%2
+     [ w        , r   , r   ; sve_int_index     ] index\t%0.<Vctype>, %<vccore>1, %<vccore>2
   }
 )
 
     operands[2] = aarch64_check_zero_based_sve_index_immediate (operands[2]);
     return "index\t%0.<Vctype>, %<vccore>1, #%2";
   }
+  [(set_attr "sve_type" "sve_int_index")]
 )
 
 ;; -------------------------------------------------------------------------
     operands[0] = gen_rtx_REG (<MODE>mode, REGNO (operands[0]));
     return "dup\t%0.<Vetype>, %1.<Vetype>[%2]";
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Extract an element outside the range of DUP.  This pattern requires the
            ? "ext\t%0.b, %0.b, %0.b, #%2"
            : "movprfx\t%0, %1\;ext\t%0.b, %0.b, %1.b, #%2");
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
           (match_operand:SVE_ALL 2 "register_operand")]
          LAST))]
   "TARGET_SVE"
-  {@ [ cons: =0 , 1   , 2  ]
-     [ ?r       , Upl , w  ] last<ab>\t%<vccore>0, %1, %2.<Vctype>
-     [ w        , Upl , w  ] last<ab>\t%<Vctype>0, %1, %2.<Vctype>
+  {@ [ cons: =0 , 1   , 2 ; attrs: sve_type ]
+     [ ?r       , Upl , w ; sve_int_extract ] last<ab>\t%<vccore>0, %1, %2.<Vctype>
+     [ w        , Upl , w ; sve_int_extract ] last<ab>\t%<Vctype>0, %1, %2.<Vctype>
   }
 )
 
      [ w        , Upl , 0 ; *              ] <sve_int_op>\t%Z0.<Vetype>, %1/m, %Z2.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%Z0, %Z2\;<sve_int_op>\t%Z0.<Vetype>, %1/m, %Z2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated integer unary arithmetic with merging.
      [ w        , Upl , 0 ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated integer unary arithmetic, merging with an independent value.
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 
      [ w        , Upl , 0 ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Another way of expressing the REVB, REVH and REVW patterns, with this
      [ w        , Upl , 0 ; *              ] rev<SVE_ALL:Vcwtype>\t%0.<PRED_HSD:Vetype>, %1/m, %2.<PRED_HSD:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;rev<SVE_ALL:Vcwtype>\t%0.<PRED_HSD:Vetype>, %1/m, %2.<PRED_HSD:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated integer unary operations with merging.
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0 ; *              ] <su>xt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<su>xt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_extend")]
 )
 
 ;; Predicated truncate-and-sign-extend operations.
      [ w        , Upl , 0 ; *              ] sxt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;sxt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_extend")]
 )
 
 ;; Predicated truncate-and-sign-extend operations with merging.
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_FULL_HSDI:Vetype>, %1/z, %2.<SVE_FULL_HSDI:Vetype>\;sxt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;sxt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_extend")]
 )
 
 ;; Predicated truncate-and-zero-extend operations, merging with the
      [ w        , Upl , 0 ; *              ] uxt%e3\t%0.<Vetype>, %1/m, %0.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;uxt%e3\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_extend")]
 )
 
 ;; Predicated truncate-and-zero-extend operations, merging with an
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;uxt%e3\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %4\;uxt%e3\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_extend")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0 ; *              ] cnot\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;cnot\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated logical inverse with merging.
   {
     operands[5] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated logical inverse, merging with an independent value.
   {
     operands[5] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE_FP_UNARY_INT))]
   "TARGET_SVE"
   "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_exp")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE_FP_UNARY))]
   "TARGET_SVE"
   "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Unpredicated floating-point unary operations.
      [ w        , Upl , 0 ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Predicated floating-point unary arithmetic with merging.
   {
     operands[3] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "*cond_<optab><mode>_2_strict"
      [ w        , Upl , 0 ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Predicated floating-point unary arithmetic, merging with an independent
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "*cond_<optab><mode>_any_strict"
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
   "TARGET_SVE"
   "not\t%0.b, %1/z, %2.b"
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Predicated predicate inverse in which the flags are set in the same
        (and:PRED_ALL (not:PRED_ALL (match_dup 2)) (match_dup 3)))]
   "TARGET_SVE"
   "nots\t%0.b, %1/z, %2.b"
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Same, where only the flags result is interesting.
    (clobber (match_scratch:PRED_ALL 0 "=Upa"))]
   "TARGET_SVE"
   "nots\t%0.b, %1/z, %2.b"
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; =========================================================================
   [(set (match_dup 0)
        (SVE_INT_BINARY_IMM:SVE_I_SIMD_DI (match_dup 2) (match_dup 3)))]
   ""
+  [(set_attr "sve_type" "sve_<sve_type_int>")]
 )
 
 ;; Unpredicated binary operations with a constant (post-RA only).
   "@
    <sve_int_op>\t%Z0.<Vetype>, %Z0.<Vetype>, #%<sve_imm_prefix>2
    movprfx\t%Z0, %Z1\;<sve_int_op>\t%Z0.<Vetype>, %Z0.<Vetype>, #%<sve_imm_prefix>2"
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_<sve_type_int>")]
 )
 
 ;; Predicated integer operations with merging.
      [ w        , Upl , 0 , w ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_int>")]
 )
 
 ;; Predicated integer operations, merging with the second input.
      [ w        , Upl , w , 0 ; *              ] <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %3\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_int>")]
 )
 
 ;; Predicated integer operations, merging with an independent value.
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_<sve_type_int>")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?w       , w  , vsn ; yes            ] movprfx\t%0, %1\;sub\t%0.<Vetype>, %0.<Vetype>, #%N2
      [ w        , w  , w   ; *              ] add\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Merging forms are handled through SVE_INT_BINARY.
      [ w        , vsa , 0 ; *              ] subr\t%0.<Vetype>, %0.<Vetype>, #%D1
      [ ?&w      , vsa , w ; yes            ] movprfx\t%0, %2\;subr\t%0.<Vetype>, %0.<Vetype>, #%D1
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Merging forms are handled through SVE_INT_BINARY.
          UNSPEC_ADR))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "adr\t%0.<Vetype>, [%1.<Vetype>, %2.<Vetype>]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Same, but with the offset being sign-extended from the low 32 bits.
   {
     operands[3] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Same, but with the offset being zero-extended from the low 32 bits.
          UNSPEC_ADR))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "adr\t%0.d, [%1.d, %2.d, uxtw]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Same, matching as a PLUS rather than unspec.
          (match_operand:VNx2DI 1 "register_operand" "w")))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "adr\t%0.d, [%1.d, %2.d, uxtw]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; ADR with a nonzero shift.
          (match_operand:SVE_24I 1 "register_operand" "w")))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "adr\t%0.<Vctype>, [%1.<Vctype>, %2.<Vctype>, lsl %3]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Same, but with the index being sign-extended from the low 32 bits.
   {
     operands[4] = CONSTM1_RTX (VNx2BImode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Same, but with the index being zero-extended from the low 32 bits.
          (match_operand:VNx2DI 1 "register_operand" "w")))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "adr\t%0.d, [%1.d, %2.d, uxtw %3]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0  , w ; *              ] <su>abd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w  , w ; yes            ] movprfx\t%0, %2\;<su>abd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_expand "@aarch64_cond_<su>abd<mode>"
   {
     operands[4] = operands[5] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated integer absolute difference, merging with the second input.
   {
     operands[4] = operands[5] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated integer absolute difference, merging with an independent value.
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , w , vsS ; yes            ] movprfx\t%0, %1\;<binqops_op_rev>\t%0.<Vetype>, %0.<Vetype>, #%N2
      [ w        , w , w   ; *              ] <binqops_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Unpredicated saturating unsigned addition and subtraction.
      [ ?&w      , w , vsa ; yes            ] movprfx\t%0, %1\;<binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
      [ w        , w , w   ; *              ] <binqops_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0  , w ; *              ] <su>mulh\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w  , w ; yes            ] movprfx\t%0, %2\;<su>mulh\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated highpart multiplications with merging.
      [ w        , Upl , 0 , w ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated highpart multiplications, merging with zero.
      [ &w       , Upl , 0  , w  ] movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ &w       , Upl , w  , w  ] movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
-  [(set_attr "movprfx" "yes")])
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_mul")]
+)
 
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Division
      [ w        , Upl , w , 0 ; *              ] <sve_int_op>r\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, %Z2.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%Z0, %Z2\;<sve_int_op>\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, %Z3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_div")]
 )
 
 ;; Predicated integer division with merging.
      [ w        , Upl , 0 , w ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_div")]
 )
 
 ;; Predicated integer division, merging with the second input.
      [ w        , Upl , w , 0 ; *              ] <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %3\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_div")]
 )
 
 ;; Predicated integer division, merging with an independent value.
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_div")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?w       , w  , vsl ; yes            ] movprfx\t%0, %1\;<logical>\t%0.<Vetype>, %0.<Vetype>, #%C2
      [ w        , w  , w   ; *              ] <logical>\t%0.d, %1.d, %2.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Merging forms are handled through SVE_INT_BINARY.
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated BIC with merging.
      [ w        , Upl , 0 , w ; *              ] bic\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;bic\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated integer BIC, merging with an independent value.
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
   "&& !register_operand (operands[3], <MODE>mode)"
   [(set (match_dup 0) (ASHIFT:SVE_I (match_dup 2) (match_dup 3)))]
   ""
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Unpredicated shift operations by a constant.
          (match_operand:SVE_I 1 "register_operand")
          (match_operand:SVE_I 2 "aarch64_simd_lshift_imm")))]
   "TARGET_SVE"
-  {@ [ cons: =0 , 1 , 2   ]
-     [ w       , w , vs1 ] add\t%0.<Vetype>, %1.<Vetype>, %1.<Vetype>
-     [ w       , w , Dl  ] lsl\t%0.<Vetype>, %1.<Vetype>, #%2
+  {@ [ cons: =0 , 1 , 2   ; attrs: sve_type ]
+     [ w       , w , vs1 ; sve_int_general    ] add\t%0.<Vetype>, %1.<Vetype>, %1.<Vetype>
+     [ w       , w , Dl  ; sve_int_shift   ] lsl\t%0.<Vetype>, %1.<Vetype>, #%2
   }
 )
 
          (match_operand:SVE_I 2 "aarch64_simd_rshift_imm")))]
   "TARGET_SVE"
   "<shift>\t%0.<Vetype>, %1.<Vetype>, #%2"
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated integer shift, merging with the first input.
      [ w        , Upl , 0 ; *              ] <shift>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<shift>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated integer shift, merging with an independent value.
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Unpredicated shifts of narrow elements by 64-bit amounts.
          SVE_SHIFT_WIDE))]
   "TARGET_SVE"
   "<sve_int_op>\t%0.<Vetype>, %1.<Vetype>, %2.d"
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Merging predicated shifts of narrow elements by 64-bit amounts.
      [ w        , Upl , 0 , w ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated shifts of narrow elements by 64-bit amounts, merging with zero.
      [ &w       , Upl , 0 , w  ] movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
      [ &w       , Upl , w , w  ] movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
   }
-  [(set_attr "movprfx" "yes")])
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_shift")])
 
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Shifts (rounding towards 0)
      [ w        , Upl , 0 ; *              ] asrd\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, #%3
      [ ?&w      , Upl , w ; yes            ] movprfx\t%Z0, %Z2\;asrd\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, #%3
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated shift with merging.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated shift, merging with an independent value.
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE_FP_BINARY_INT))]
   "TARGET_SVE"
   "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Predicated floating-point binary operations that take an integer
      [ w        , Upl , 0 , w ; *              ] <sve_fp_op>\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, %Z3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%Z0, %Z2\;<sve_fp_op>\t%Z0.<Vetype>, %1/m, %Z0.<Vetype>, %Z3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Predicated floating-point binary operations with merging, taking an
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "*cond_<optab><mode>_2_strict"
      [ w        , Upl , 0 , w ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Predicated floating-point binary operations that take an integer as
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn_and_rewrite "*cond_<optab><mode>_any_strict"
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:SVE_F_B16B16 1 "register_operand" "w")
          (match_operand:SVE_F_B16B16 2 "register_operand" "w")))]
   "TARGET_SVE && reload_completed"
-  "<b><sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>")
+  "<b><sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_<sve_type_fp>")]
+)
 
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] General binary arithmetic corresponding to unspecs
          SVE_FP_BINARY))]
   "TARGET_SVE"
   "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Unpredicated floating-point binary operations that need to be predicated
      [ w        , Upl , w , 0 ; *              ] <sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Predicated floating-point operations with merging.
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "*cond_<optab><mode>_2_strict"
      [ w        , Upl , 0 , w ; *              ] <b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Same for operations that take a 1-bit constant.
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "*cond_<optab><mode>_2_const_strict"
      [ w        , Upl , 0 ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
      [ ?w       , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Predicated floating-point operations, merging with the second input.
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "*cond_<optab><mode>_3_strict"
      [ w        , Upl , w , 0 ; *              ] <b><sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %3\;<b><sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Predicated floating-point operations, merging with an independent value.
   }
   [(set_attr "movprfx" "yes")
    (set_attr "is_bf16" "<is_bf16>")
-   (set_attr "supports_bf16_rev" "<supports_bf16_rev>")]
+   (set_attr "supports_bf16_rev" "<supports_bf16_rev>")
+   (set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn_and_rewrite "*cond_<optab><mode>_any_strict"
   }
   [(set_attr "movprfx" "yes")
    (set_attr "is_bf16" "<is_bf16>")
-   (set_attr "supports_bf16_rev" "<supports_bf16_rev>")]
+   (set_attr "supports_bf16_rev" "<supports_bf16_rev>")
+   (set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Same for operations that take a 1-bit constant.
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn_and_rewrite "*cond_<optab><mode>_any_const_strict"
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , Upl , w  , vsN , i   ; yes            ] movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
      [ ?&w      , Upl , w  , w   , Ui1 ; yes            ] movprfx\t%0, %2\;fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Predicated floating-point addition of a constant, merging with the
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn "*cond_add<mode>_2_const_strict"
      [ ?w       , Upl , w , vsA ; yes            ] movprfx\t%0, %2\;fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
      [ ?w       , Upl , w , vsN ; yes            ] movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Predicated floating-point addition of a constant, merging with an
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn_and_rewrite "*cond_add<mode>_any_const_strict"
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Register merging forms are handled through SVE_COND_FP_BINARY.
      [ w        , Upl , 0 , w ; *              ] fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
   }
+  [(set_attr "sve_type" "sve_fp_misc")]
 )
 
 ;; Predicated FCADD with merging.
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_misc")]
 )
 
 (define_insn "*cond_<optab><mode>_2_strict"
      [ w        , Upl , 0 , w ; *              ] fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
   }
+  [(set_attr "sve_type" "sve_fp_misc")]
 )
 
 ;; Predicated FCADD, merging with an independent value.
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_misc")]
 )
 
 (define_insn_and_rewrite "*cond_<optab><mode>_any_strict"
                                             operands[4], operands[1]));
     operands[4] = operands[2] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_misc")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , Upl , vsA , w , i   ; yes            ] movprfx\t%0, %3\;fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
      [ ?&w      , Upl , w   , w , Ui1 ; yes            ] movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Predicated floating-point subtraction from a constant, merging with the
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn "*cond_sub<mode>_3_const_strict"
      [ w        , Upl , 0 ; *              ] fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
      [ ?w       , Upl , w ; yes            ] movprfx\t%0, %3\;fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Predicated floating-point subtraction from a constant, merging with an
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn_and_rewrite "*cond_sub<mode>_const_strict"
                                              operands[4], operands[1]));
     operands[4] = operands[3] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_arith")]
 )
 ;; Register merging forms are handled through SVE_COND_FP_BINARY.
 
   {
     operands[5] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn "*aarch64_pred_abd<mode>_strict"
      [ w        , Upl , 0  , w ; *              ] fabd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w  , w ; yes            ] movprfx\t%0, %2\;fabd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_expand "@aarch64_cond_abd<mode>"
     operands[4] = copy_rtx (operands[1]);
     operands[5] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn "*aarch64_cond_abd<mode>_2_strict"
      [ w        , Upl , 0 , w ; *              ] fabd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;fabd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Predicated floating-point absolute difference, merging with the second
     operands[4] = copy_rtx (operands[1]);
     operands[5] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn "*aarch64_cond_abd<mode>_3_strict"
      [ w        , Upl , w , 0 ; *              ] fabd\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %3\;fabd\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Predicated floating-point absolute difference, merging with an
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn_and_rewrite "*aarch64_cond_abd<mode>_any_strict"
                                             operands[4], operands[1]));
     operands[4] = operands[3] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , Upl , w  , vsM , i   ; yes            ] movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
      [ ?&w      , Upl , w  , w   , Ui1 ; yes            ] movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Merging forms are handled through SVE_COND_FP_BINARY and
          (match_operand:SVE_FULL_F_B16B16 1 "register_operand" "w")))]
   "TARGET_SVE"
   "<b>fmul\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]"
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; -------------------------------------------------------------------------
          LOGICALF))]
   "TARGET_SVE"
   "<logicalf_op>\t%0.d, %1.d, %2.d"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , Upl , w  , vsB ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
      [ ?&w      , Upl , w  , w   ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; Merging forms are handled through SVE_COND_FP_BINARY and
      [ ?Upa    , 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Unpredicated predicate EOR and ORR.
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Perform a logical operation on operands 2 and 3, using operand 1 as
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Same with just the flags result.
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Same, but set the flags as a side-effect.
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Same with just the flags result.
      [ ?Upa     , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa      , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Same, but set the flags as a side-effect.
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; Same with just the flags result.
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; =========================================================================
      [ w        , Upl , w  , w , 0 ; *              ] mla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w  , w , w ; yes            ] movprfx\t%0, %4\;mla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated integer addition of product with merging.
      [ w        , Upl , 0 , w , w ; *              ] mad\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %2\;mad\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated integer addition of product, merging with the third input.
      [ w        , Upl , w , w , 0 ; *              ] mla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %4\;mla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated integer addition of product, merging with an independent value.
                                             operands[5], operands[1]));
     operands[5] = operands[4] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , w  , w , 0 ; *              ] mls\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w  , w , w ; yes            ] movprfx\t%0, %4\;mls\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated integer subtraction of product with merging.
      [ w        , Upl , 0 , w , w ; *              ] msb\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %2\;msb\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated integer subtraction of product, merging with the third input.
      [ w        , Upl , w , w , 0 ; *              ] mls\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %4\;mls\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; Predicated integer subtraction of product, merging with an
                                             operands[5], operands[1]));
     operands[5] = operands[4] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , w , w , 0 ; *              ] <sur>dot\t%0.<Vetype>, %1.<Vetype_fourth>, %2.<Vetype_fourth>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %3\;<sur>dot\t%0.<Vetype>, %1.<Vetype_fourth>, %2.<Vetype_fourth>
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 ;; Four-element integer dot-product by selected lanes with accumulation.
      [ w        , w , <SVE_FULL_SDI:sve_lane_con> , 0 ; *              ] <sur>dot\t%0.<SVE_FULL_SDI:Vetype>, %1.<SVE_FULL_BHI:Vetype>, %2.<SVE_FULL_BHI:Vetype>[%3]
      [ ?&w      , w , <SVE_FULL_SDI:sve_lane_con> , w ; yes            ] movprfx\t%0, %4\;<sur>dot\t%0.<SVE_FULL_SDI:Vetype>, %1.<SVE_FULL_BHI:Vetype>, %2.<SVE_FULL_BHI:Vetype>[%3]
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 (define_insn "@<sur>dot_prod<mode><vsi2qi>"
      [ w        , w , w , 0 ; *              ] <sur>dot\t%0.s, %1.b, %2.b
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %3\;<sur>dot\t%0.s, %1.b, %2.b
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 (define_insn "@aarch64_<sur>dot_prod_lane<VNx4SI_ONLY:mode><VNx16QI_ONLY:mode>"
      [ w        , w , y , 0 ; *              ] <sur>dot\t%0.s, %1.b, %2.b[%3]
      [ ?&w      , w , y , w ; yes            ] movprfx\t%0, %4\;<sur>dot\t%0.s, %1.b, %2.b[%3]
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , w ; *              ] <sur>mmla\t%0.s, %2.b, %3.b
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sur>mmla\t%0.s, %2.b, %3.b
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , Upl , w  , w , w ; yes , *    ] movprfx\t%0, %4\;<b><sve_fmla_op>\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   }
   [(set_attr "is_bf16" "<is_bf16>")
-   (set_attr "supports_bf16_rev" "false")]
+   (set_attr "supports_bf16_rev" "false")
+   (set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Predicated floating-point ternary operations with merging.
   {
     operands[5] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "*cond_<optab><mode>_2_strict"
      [ w        , Upl , 0 , w , w ; *              ] <sve_fmad_op>\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %2\;<sve_fmad_op>\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Predicated floating-point ternary operations, merging with the
   {
     operands[5] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "*cond_<optab><mode>_4_strict"
      [ w        , Upl , w , w , 0 ; *              ] <b><sve_fmla_op>\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %4\;<b><sve_fmla_op>\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Predicated floating-point ternary operations, merging with an
   }
   [(set_attr "movprfx" "yes")
    (set_attr "is_bf16" "<is_bf16>")
-   (set_attr "supports_bf16_rev" "false")]
+   (set_attr "supports_bf16_rev" "false")
+   (set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn_and_rewrite "*cond_<optab><mode>_any_strict"
   }
   [(set_attr "movprfx" "yes")
    (set_attr "is_bf16" "<is_bf16>")
-   (set_attr "supports_bf16_rev" "false")]
+   (set_attr "supports_bf16_rev" "false")
+   (set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Unpredicated FMLA and FMLS by selected lanes.  It doesn't seem worth using
      [ w        , w , <sve_lane_con> , 0 ; *              ] <b><sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]
      [ ?&w      , w , <sve_lane_con> , w ; yes            ] movprfx\t%0, %4\;<b><sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , w , w , 0 ; *              ] fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; unpredicated optab pattern for auto-vectorizer
   {
     operands[5] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "*cond_<optab><mode>_4_strict"
      [ w        , Upl , w , w , 0 ; *              ] fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
      [ ?&w      , Upl , w , w , w ; yes            ] movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Predicated FCMLA, merging with an independent value.
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn_and_rewrite "*cond_<optab><mode>_any_strict"
                                             operands[5], operands[1]));
     operands[5] = operands[4] = operands[0];
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; Unpredicated FCMLA with indexing.
      [ w        , w , <sve_lane_pair_con> , 0 ; *              ] fcmla\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3], #<rot>
      [ ?&w      , w , <sve_lane_pair_con> , w ; yes            ] movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3], #<rot>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w ; *              ] ftmad\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #%3
      [ ?&w      , w , w ; yes            ] movprfx\t%0, %1\;ftmad\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #%3
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , w ; *              ] <sve_fp_op>\t%0.s, %2.h, %3.h
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_fp_op>\t%0.s, %2.h, %3.h
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; The immediate range is enforced before generating the instruction.
      [ w        , 0 , w , y ; *              ] <sve_fp_op>\t%0.s, %2.h, %3.h[%4]
      [ ?&w      , w , w , y ; yes            ] movprfx\t%0, %1\;<sve_fp_op>\t%0.s, %2.h, %3.h[%4]
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , w ; *              ] <sve_fp_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_fp_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; =========================================================================
      [ ?Upl     , 0  , w , w            ; yes                 ] ^
      [ Upa      , Upl, w , w            ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 ;; Likewise, but yield a VNx16BI result regardless of the element width.
     operands[6] = copy_rtx (operands[4]);
     operands[7] = operands[5];
   }
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 (define_insn_and_rewrite "*cmp<cmp_op><mode>_acle_cc"
     operands[6] = copy_rtx (operands[4]);
     operands[7] = operands[5];
   }
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 ;; Predicated integer comparisons, formed by combining a PTRUE-predicated
                (match_dup 3))]
             UNSPEC_PRED_Z))
       (clobber (reg:CC_NZC CC_REGNUM))])]
+  {}
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 (define_insn_and_split "*cmp<cmp_op><mode>_acle_and"
      [ ?Upl    ,  0  ,  , w, w; yes                 ] ^
      [ Upa     ,  Upl,  , w, w; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 (define_expand "@aarch64_pred_cmp<cmp_op><mode>_wide"
     operands[6] = copy_rtx (operands[4]);
     operands[7] = operands[5];
   }
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 (define_insn_and_rewrite "*aarch64_pred_cmp<cmp_op><mode>_wide_cc"
     operands[6] = copy_rtx (operands[4]);
     operands[7] = operands[5];
   }
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 ;; Predicated integer wide comparisons in which only the flags result
     operands[6] = copy_rtx (operands[4]);
     operands[7] = operands[5];
   }
+  [(set_attr "sve_type" "sve_int_cmp_set")]
 )
 
 ;; -------------------------------------------------------------------------
    (clobber (reg:CC_NZC CC_REGNUM))]
   "TARGET_SVE"
   "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; Likewise, but yield a VNx16BI result regardless of the element width.
     operands[3] = CONSTM1_RTX (VNx16BImode);
     operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 (define_insn_and_rewrite "*while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle_cc"
     operands[3] = CONSTM1_RTX (VNx16BImode);
     operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; -------------------------------------------------------------------------
      [ Upa      , Upl , w , Dz  ] fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, #0.0
      [ Upa      , Upl , w , w   ] fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 (define_expand "@aarch64_pred_fcm<cmp_op><mode>_acle"
          UNSPEC_COND_FCMUO))]
   "TARGET_SVE"
   "fcmuo\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 (define_expand "@aarch64_pred_fcmuo<mode>_acle"
           (match_dup 2)
           (match_dup 3)]
          SVE_COND_FP_CMP_I0))]
+  {}
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 ;; Same for unordered comparisons.
           (match_dup 2)
           (match_dup 3)]
          UNSPEC_COND_FCMUO))]
+  {}
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 ;; Similar to *fcm<cmp_op><mode>_and_combine, but for BIC rather than AND.
   if (can_create_pseudo_p ())
     operands[5] = gen_reg_rtx (<VPRED>mode);
 }
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 ;; Make sure that we expand to a nor when the operand 4 of
   if (can_create_pseudo_p ())
     operands[5] = gen_reg_rtx (<VPRED>mode);
 }
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 ;; Same for unordered comparisons.
   if (can_create_pseudo_p ())
     operands[5] = gen_reg_rtx (<VPRED>mode);
 }
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 (define_insn_and_split "*fcmuo<mode>_nor_combine"
   if (can_create_pseudo_p ())
     operands[5] = gen_reg_rtx (<VPRED>mode);
 }
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 ;; -------------------------------------------------------------------------
     operands[5] = copy_rtx (operands[1]);
     operands[6] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 (define_insn "*aarch64_pred_fac<cmp_op><mode>_strict"
          SVE_COND_FP_ABS_CMP))]
   "TARGET_SVE"
   "fac<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_cmp")]
 )
 
 (define_insn "*aarch64_pred_fac<cmp_op><mode>_strict_acle"
            (match_operand:PRED_ALL 2 "register_operand" "Upa"))))]
   "TARGET_SVE"
   "sel\t%0.b, %3, %1.b, %2.b"
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; -------------------------------------------------------------------------
                       UNSPEC_PTEST))]
   "TARGET_SVE"
   "ptest\t%0, %3.b"
+  [(set_attr "sve_type" "sve_pred_logical")]
 )
 
 ;; =========================================================================
           (match_operand:SVE_ALL 3 "register_operand")]
          CLAST))]
   "TARGET_SVE"
-  {@ [ cons: =0 , 1 , 2   , 3  ]
-     [ ?r       , 0 , Upl , w  ] clast<ab>\t%<vccore>0, %2, %<vccore>0, %3.<Vctype>
-     [ w        , 0 , Upl , w  ] clast<ab>\t%<Vctype>0, %2, %<Vctype>0, %3.<Vctype>
+  {@ [ cons: =0 , 1 , 2   , 3 ]
+     [ ?r       , 0 , Upl , w ] clast<ab>\t%<vccore>0, %2, %<vccore>0, %3.<Vctype>
+     [ w        , 0 , Upl , w ] clast<ab>\t%<Vctype>0, %2, %<Vctype>0, %3.<Vctype>
   }
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 (define_insn "@aarch64_fold_extract_vector_<last_op>_<mode>"
      [ w        , 0 , Upl , w  ] clast<ab>\t%0.<Vctype>, %2, %0.<Vctype>, %3.<Vctype>
      [ ?&w      , w , Upl , w  ] movprfx\t%0, %1\;clast<ab>\t%0.<Vctype>, %2, %0.<Vctype>, %3.<Vctype>
   }
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 ;; -------------------------------------------------------------------------
                   SVE_INT_ADDV))]
   "TARGET_SVE && <max_elem_bits> >= <elem_bits>"
   "<su>addv\t%d0, %1, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_reduc")]
 )
 
 ;; Unpredicated integer reductions.
                      SVE_INT_REDUCTION))]
   "TARGET_SVE"
   "<sve_int_op>\t%<Vetype>0, %1, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_reduc")]
 )
 
 ;; -------------------------------------------------------------------------
                      SVE_FP_REDUCTION))]
   "TARGET_SVE"
   "<sve_fp_op>\t%<Vetype>0, %1, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_reduc")]
 )
 
 ;; -------------------------------------------------------------------------
                      UNSPEC_FADDA))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "fadda\t%<Vetype>0, %3, %<Vetype>0, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_assoc_add")]
 )
 
 ;; =========================================================================
          SVE_TBL))]
   "TARGET_SVE"
   "<perm_insn>\t%0.<Vetype>, {%1.<Vetype>}, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_SVE_COMPACT))]
   "TARGET_SVE && TARGET_NON_STREAMING"
   "compact\t%0.<Vetype>, %1, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 ;; Duplicate one element of a vector.
   "TARGET_SVE
    && IN_RANGE (INTVAL (operands[2]) * <container_bits> / 8, 0, 63)"
   "dup\t%0.<Vctype>, %1.<Vctype>[%2]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Use DUP.Q to duplicate a 128-bit segment of a register.
     operands[2] = gen_int_mode (byte / 16, DImode);
     return "dup\t%0.q, %1.q[%2]";
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Reverse the order of elements within a full vector.
          [(match_operand:SVE_ALL 1 "register_operand" "w")]
          UNSPEC_REV))]
   "TARGET_SVE"
-  "rev\t%0.<Vctype>, %1.<Vctype>")
+  "rev\t%0.<Vctype>, %1.<Vctype>"
+  [(set_attr "sve_type" "sve_int_general")]
+)
 
 ;; -------------------------------------------------------------------------
 ;; ---- [INT,FP] Special-purpose binary permutes
      [ w        , Upl , 0 , w ; *              ] splice\t%0.<Vetype>, %1, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;splice\t%0.<Vetype>, %1, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 ;; Permutes that take half the elements from one vector and half the
          SVE_PERMUTE))]
   "TARGET_SVE"
   "<perm_insn>\t%0.<Vctype>, %1.<Vctype>, %2.<Vctype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Apply PERMUTE to 128-bit sequences.  The behavior of these patterns
          PERMUTEQ))]
   "TARGET_SVE_F64MM"
   "<perm_insn>\t%0.q, %1.q, %2.q"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Concatenate two vectors and extract a subvector.  Note that the
            ? "ext\\t%0.b, %0.b, %2.b, #%3"
            : "movprfx\t%0, %1\;ext\\t%0.b, %0.b, %2.b, #%3");
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
                         UNSPEC_REV))]
   "TARGET_SVE"
   "rev\t%0.<Vetype>, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 (define_expand "@aarch64_sve_rev<mode>_acle"
          UNSPEC_REV_PRED))]
   "TARGET_SVE"
   "rev\t%0.<Vetype>, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; -------------------------------------------------------------------------
                         PERMUTE))]
   "TARGET_SVE"
   "<perm_insn>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; Special-purpose permutes used by the ACLE intrinsics and predicate
                        UNSPEC_PERMUTE_PRED))]
   "TARGET_SVE"
   "<perm_insn>\t%0.<PRED_ALL:Vetype>, %1.<PRED_ALL:Vetype>, %2.<PRED_ALL:Vetype>"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; =========================================================================
          UNSPEC_PACK))]
   "TARGET_SVE"
   "uzp1\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Integer partial pack packing two partial SVE types into a single full SVE
          (match_operand:<VHALF> 2 "register_operand" "w")))]
   "TARGET_SVE"
   "uzp1\t%0.<Vctype>, %1.<Vctype>, %2.<Vctype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          UNPACK))]
   "TARGET_SVE"
   "<su>unpk<perm_hilo>\t%0.<Vewtype>, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0 ; *              ] fcvtz<su>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_F:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;fcvtz<su>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_F:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; As above, for pairs used by the auto-vectorizer only.
      [ w        , Upl , 0 ; *              ] fcvtz<su>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_PARTIAL_F:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;fcvtz<su>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_PARTIAL_F:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated narrowing float-to-integer conversion.  The VNx2DF->VNx4SI
      [ w        , Upl , 0 ; *              ] fcvtz<su>\t%0.<SVE_SI:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;fcvtz<su>\t%0.<SVE_SI:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated float-to-integer conversion with merging, either to the same
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; As above, for pairs that are used by the auto-vectorizer only.
      [ &w       , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_FULL_HSDI:Vetype>, %1/z, %2.<SVE_FULL_HSDI:Vetype>\;fcvtz<su>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_F:Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvtz<su>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_F:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated narrowing float-to-integer conversion with merging.
      [ &w       , Upl , w , Dz ; yes            ] movprfx\t%0.<VNx2DF_ONLY:Vetype>, %1/z, %2.<VNx2DF_ONLY:Vetype>\;fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn_and_rewrite "*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx2SI_ONLY:mode>_relaxed"
      [ w        , Upl , 0 ; *              ] <su>cvtf\t%0.<SVE_FULL_F:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<su>cvtf\t%0.<SVE_FULL_F:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_cvt")]
 )
 
 ;; As above, for pairs that are used by the auto-vectorizer only.
      [ w        , Upl , 0 ; *              ] <su>cvtf\t%0.<SVE_PARTIAL_F:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<su>cvtf\t%0.<SVE_PARTIAL_F:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_cvt")]
 )
 
 ;; Predicated widening integer-to-float conversion.
      [ w        , Upl , 0 ; *              ] <su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_cvt")]
 )
 
 ;; Predicated integer-to-float conversion with merging, either to the same
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_int_cvt")]
 )
 
 ;; As above, for pairs that are used by the auto-vectorizer only.
      [ &w       , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_FULL_HSDI:Vetype>, %1/z, %2.<SVE_FULL_HSDI:Vetype>\;<su>cvtf\t%0.<SVE_FULL_F:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<su>cvtf\t%0.<SVE_FULL_F:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_cvt")]
 )
 
 ;; Predicated widening integer-to-float conversion with merging.
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<VNx2DF_ONLY:Vetype>, %1/z, %2.<VNx2DF_ONLY:Vetype>\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
   }
+  [(set_attr "sve_type" "sve_int_cvt")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0 ; *              ] fcvt\t%0.<SVE_FULL_HSF:Vetype>, %1/m, %2.<SVE_FULL_SDF:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;fcvt\t%0.<SVE_FULL_HSF:Vetype>, %1/m, %2.<SVE_FULL_SDF:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; As above, for pairs that are used by the auto-vectorizer only.
      [ w        , Upl , 0 ; *              ] fcvt\t%0.<SVE_PARTIAL_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;fcvt\t%0.<SVE_PARTIAL_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated float-to-float truncation with merging.
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_FULL_SDF:Vetype>, %1/z, %2.<SVE_FULL_SDF:Vetype>\;fcvt\t%0.<SVE_FULL_HSF:Vetype>, %1/m, %2.<SVE_FULL_SDF:Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvt\t%0.<SVE_FULL_HSF:Vetype>, %1/m, %2.<SVE_FULL_SDF:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; As above, for pairs that are used by the auto-vectorizer only.
      [ w        , Upl , 0 ; *              ] bfcvt\t%0.h, %1/m, %2.s
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;bfcvt\t%0.h, %1/m, %2.s
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated BFCVT with merging.
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.s, %1/z, %2.s\;bfcvt\t%0.h, %1/m, %2.s
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;bfcvt\t%0.h, %1/m, %2.s
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated BFCVTNT.  This doesn't give a natural aarch64_pred_*/cond_*
          UNSPEC_COND_FCVTNT))]
   "TARGET_SVE_BF16"
   "bfcvtnt\t%0.h, %2/m, %3.s"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0 ; *              ] fcvt\t%0.<SVE_FULL_SDF:Vetype>, %1/m, %2.<SVE_FULL_HSF:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;fcvt\t%0.<SVE_FULL_SDF:Vetype>, %1/m, %2.<SVE_FULL_HSF:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; As above, for pairs that are used by the auto-vectorizer only.
      [ w        , Upl , 0 ; *              ] fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_PARTIAL_HSF:Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_PARTIAL_HSF:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated float-to-float extension with merging.
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_FULL_SDF:Vetype>, %1/z, %2.<SVE_FULL_SDF:Vetype>\;fcvt\t%0.<SVE_FULL_SDF:Vetype>, %1/m, %2.<SVE_FULL_HSF:Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvt\t%0.<SVE_FULL_SDF:Vetype>, %1/m, %2.<SVE_FULL_HSF:Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; As above, for pairs that are used by the auto-vectorizer only.
          UNSPEC_PACK))]
   "TARGET_SVE"
   "uzp1\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; -------------------------------------------------------------------------
                        UNPACK_UNSIGNED))]
   "TARGET_SVE"
   "punpk<perm_hilo>\t%0.h, %1.b"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 (define_expand "@aarch64_sve_punpk<perm_hilo>_acle"
      [ ?Upa     ,  0Upa, 0Upa, 0 ; yes                 ] ^
      [ Upa      ,  Upa , Upa , 0 ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; Same, but also producing a flags result.
      [ ?Upa    , 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; Same, but with only the flags result being interesting.
      [ ?Upa    , 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?Upa    , 0Upa, 0Upa, 0<brk_reg_con>; yes                 ] ^
      [ Upa     , Upa , Upa , <brk_reg_con> ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; BRKN, producing both a predicate and a flags result.  Unlike other
     operands[4] = CONST0_RTX (VNx16BImode);
     operands[5] = CONST0_RTX (VNx16BImode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; Same, but with only the flags result being interesting.
     operands[4] = CONST0_RTX (VNx16BImode);
     operands[5] = CONST0_RTX (VNx16BImode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; BRKPA and BRKPB, producing both a predicate and a flags result.
      [ ?Upa    , 0Upa, 0Upa, 0Upa,  ; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ,  ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; Same, but with only the flags result being interesting.
      [ ?Upa    , 0Upa, 0Upa, 0Upa; yes                 ] ^
      [ Upa     , Upa , Upa , Upa ; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; -------------------------------------------------------------------------
    (clobber (reg:CC_NZC CC_REGNUM))]
   "TARGET_SVE"
   "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; Same, but also producing a flags result.
     operands[4] = operands[2];
     operands[5] = operands[3];
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 (define_insn_and_rewrite "*aarch64_sve_<sve_pred_op><mode>_cc"
     operands[4] = operands[2];
     operands[5] = operands[3];
   }
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; =========================================================================
   {
     return aarch64_output_sve_cnt_pat_immediate ("cnt", "%x0", operands + 1);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; -------------------------------------------------------------------------
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%x0",
                                                 operands + 2);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Increment an SImode register by the number of elements in an svpattern
   {
     return aarch64_output_sve_cnt_pat_immediate ("inc", "%x0", operands + 2);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Increment an SImode register by the number of elements in an svpattern
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", registers,
                                                 operands + 2);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; -------------------------------------------------------------------------
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
                                                 operands + 2);
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Increment a vector of SIs by the number of elements in an svpattern.
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
                                                 operands + 2);
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Increment a vector of HIs by the number of elements in an svpattern.
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
                                                 operands + 2);
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; -------------------------------------------------------------------------
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%x0",
                                                 operands + 2);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Decrement an SImode register by the number of elements in an svpattern
   {
     return aarch64_output_sve_cnt_pat_immediate ("dec", "%x0", operands + 2);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Decrement an SImode register by the number of elements in an svpattern
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", registers,
                                                 operands + 2);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; -------------------------------------------------------------------------
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
                                                 operands + 2);
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Decrement a vector of SIs by the number of elements in an svpattern.
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
                                                 operands + 2);
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Decrement a vector of HIs by the number of elements in an svpattern.
     return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
                                                 operands + 2);
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; -------------------------------------------------------------------------
                      (match_operand:PRED_ALL 3 "register_operand" "Upa")]
                     UNSPEC_CNTP)))]
   "TARGET_SVE"
-  "cntp\t%x0, %1, %3.<Vetype>")
+  "cntp\t%x0, %1, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
+)
 
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Increment by the number of elements in a predicate (scalar)
   {
     operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Increment an SImode register by the number of set bits in a predicate
   {
     operands[3] = CONSTM1_RTX (<MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Increment an SImode register by the number of set bits in a predicate
   {
     operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Increment a vector of SIs by the number of set bits in a predicate.
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Increment a vector of HIs by the number of set bits in a predicate.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Decrement an SImode register by the number of set bits in a predicate
   {
     operands[3] = CONSTM1_RTX (<MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; Decrement an SImode register by the number of set bits in a predicate
   {
     operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
   }
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Decrement a vector of SIs by the number of set bits in a predicate.
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; Decrement a vector of HIs by the number of set bits in a predicate.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 (define_insn_and_split "@aarch64_sve_get_neonq_<mode>"
   "TARGET_SVE
    && BYTES_BIG_ENDIAN"
   "sel\t%0.<Vetype>, %3, %Z2.<Vetype>, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
index a3cbbce8b31168ec4a4e2f8ecdecaf4260b782a3..69a376706facaa5f0dd5032fa30cb9298d222568 100644 (file)
          UNSPEC_PMOV_UNPACK))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "pmov\t%0, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 (define_insn "@aarch64_pmov_lane_to_<mode>"
          UNSPEC_PMOV_UNPACK_LANE))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "pmov\t%0[%3], %2.<Vetype>"
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_PMOV_PACK))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "pmov\t%0.<Vetype>, %1"
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 (define_insn "@aarch64_pmov_lane_from_<mode>"
          UNSPEC_PMOV_PACK_LANE))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "pmov\t%0.<Vetype>, %1[%2]"
+  [(set_attr "sve_type" "sve_pred_vec")]
 )
 
 ;; =========================================================================
          UNSPEC_LD1_EXTENDQ))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "ld1<Vesize>\t{%0.q}, %2/z, %1"
+  [(set_attr "sve_type" "sve_load_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_LDNQ))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "ld<vector_count>q\t{%S0.q - %<Vendreg>0.q}, %2/z, %1"
+  [(set_attr "sve_type" "sve_load_<vector_count>reg")]
 )
 
 ;; -------------------------------------------------------------------------
          LD1_COUNT))]
   "TARGET_SVE2p1_OR_SME2"
   "<optab><Vesize>\t%0, %K2/z, %1"
-  [(set_attr "stride_type" "ld1_consecutive")]
+  [(set_attr "stride_type" "ld1_consecutive")
+   (set_attr "sve_type" "sve_load_<vector_count>reg")]
 )
 
 (define_insn "@aarch64_<optab><mode>_strided2"
   "TARGET_STREAMING_SME2
    && aarch64_strided_registers_p (operands, 2, 8)"
   "<optab><Vesize>\t{%0.<Vetype>, %1.<Vetype>}, %K3/z, %2"
-  [(set_attr "stride_type" "ld1_strided")]
+  [(set_attr "stride_type" "ld1_strided")
+   (set_attr "sve_type" "sve_load_2reg")]
 )
 
 (define_insn "@aarch64_<optab><mode>_strided4"
   "TARGET_STREAMING_SME2
    && aarch64_strided_registers_p (operands, 4, 4)"
   "<optab><Vesize>\t{%0.<Vetype>, %1.<Vetype>, %2.<Vetype>, %3.<Vetype>}, %K5/z, %4"
-  [(set_attr "stride_type" "ld1_strided")]
+  [(set_attr "stride_type" "ld1_strided")
+   (set_attr "sve_type" "sve_load_4reg")]
 )
 
 ;; -------------------------------------------------------------------------
      [&w, Upl, r, w] ld1q\t{%0.q}, %1/z, [%3.d, %2]
      [?w, Upl, r, 0] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; -------------------------------------------------------------------------
      [&w, Upl, r, w    ] ldnt1<Vesize>\t%0.<Vetype>, %1/z, [%3.<Vetype>, %2]
      [?w, Upl, r, 0    ] ^
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; Extending loads.
   {
     operands[4] = CONSTM1_RTX (<SVE_FULL_SDI:VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_gatherload_64")]
 )
 
 ;; =========================================================================
          UNSPEC_ST1_TRUNCQ))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "st1<Vesize>\t{%1.q}, %2, %0"
+  [(set_attr "sve_type" "sve_store_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_STNQ))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "st<vector_count>q\t{%S1.q - %<Vendreg>1.q}, %2, %0"
+  [(set_attr "sve_type" "sve_store_<vector_count>reg")]
 )
 
 ;; -------------------------------------------------------------------------
          ST1_COUNT))]
   "TARGET_SVE2p1_OR_SME2"
   "<optab><Vesize>\t%1, %K2, %0"
-  [(set_attr "stride_type" "st1_consecutive")]
+  [(set_attr "stride_type" "st1_consecutive")
+   (set_attr "sve_type" "sve_store_1reg")]
 )
 
 (define_insn "@aarch64_<optab><mode>_strided2"
   "TARGET_STREAMING_SME2
    && aarch64_strided_registers_p (operands + 2, 2, 8)"
   "<optab><Vesize>\t{%2.<Vetype>, %3.<Vetype>}, %K1, %0"
-  [(set_attr "stride_type" "st1_strided")]
+  [(set_attr "stride_type" "st1_strided")
+   (set_attr "sve_type" "sve_store_1reg")]
 )
 
 (define_insn "@aarch64_<optab><mode>_strided4"
   "TARGET_STREAMING_SME2
    && aarch64_strided_registers_p (operands + 2, 4, 4)"
   "<optab><Vesize>\t{%2.<Vetype>, %3.<Vetype>, %4.<Vetype>, %5.<Vetype>}, %K1, %0"
-  [(set_attr "stride_type" "st1_strided")]
+  [(set_attr "stride_type" "st1_strided")
+   (set_attr "sve_type" "sve_store_1reg")]
 )
 
 ;; -------------------------------------------------------------------------
      [ Upl     , Z , w , w  ] st1q\t{%3.q}, %0, [%2.d]
      [ Upl     , r , w , w  ] st1q\t{%3.q}, %0, [%2.d, %1]
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; -------------------------------------------------------------------------
      [ Upl     , Z , w , w  ] stnt1<Vesize>\t%3.<Vetype>, %0, [%2.<Vetype>]
      [ Upl     , r , w , w  ] stnt1<Vesize>\t%3.<Vetype>, %0, [%2.<Vetype>, %1]
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; Truncating stores.
      [ Upl     , Z , w , w  ] stnt1<SVE_PARTIAL_I:Vesize>\t%3.<SVE_FULL_SDI:Vetype>, %0, [%2.<SVE_FULL_SDI:Vetype>]
      [ Upl     , r , w , w  ] stnt1<SVE_PARTIAL_I:Vesize>\t%3.<SVE_FULL_SDI:Vetype>, %0, [%2.<SVE_FULL_SDI:Vetype>, %1]
   }
+  [(set_attr "sve_type" "sve_scatterstore_64")]
 )
 
 ;; =========================================================================
        (unspec:VNx16BI [(const_int BHSD_BITS)] UNSPEC_PTRUE_C))]
   "TARGET_SVE2p1_OR_SME2"
   "ptrue\t%K0.<bits_etype>"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_PEXT))]
   "TARGET_SVE2p1_OR_SME2"
   "pext\t%0.<bits_etype>, %K1[%2]"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 (define_insn "@aarch64_sve_pext<BHSD_BITS>x2"
          UNSPEC_PEXTx2))]
   "TARGET_SVE2p1_OR_SME2"
   "pext\t{%S0.<bits_etype>, %T0.<bits_etype>}, %K1[%2]"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_PSEL))]
   "TARGET_SVE2p1_OR_SME"
   "psel\t%0, %1, %2.<bits_etype>[%w3, 0]"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 (define_insn "*aarch64_sve_psel<BHSD_BITS>_plus"
   "TARGET_SVE2p1_OR_SME
    && UINTVAL (operands[4]) < 128 / <BHSD_BITS>"
   "psel\t%0, %1, %2.<bits_etype>[%w3, %4]"
+  [(set_attr "sve_type" "sve_pred_misc")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_CNTP_C))]
   "TARGET_SVE2p1_OR_SME2"
   "cntp\t%x0, %K1.<bits_etype>, vlx%2"
+  [(set_attr "sve_type" "sve_pred_cnt_scalar")]
 )
 
 ;; =========================================================================
          SVE2_SFx24_UNARY))]
   "TARGET_STREAMING_SME2"
   "frint<frint_suffix>\t%0, %1"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; =========================================================================
          (match_operand:SVE_Ix24 2 "aligned_register_operand" "Uw<vector_count>")))]
   "TARGET_STREAMING_SME2"
   "<sve_int_op>\t%0, %0, %2"
+  [(set_attr "sve_type" "sve_<sve_type_int>")]
 )
 
 (define_insn "@aarch64_sve_single_<optab><mode>"
            (match_operand:<VSINGLE> 2 "register_operand" "x"))))]
   "TARGET_STREAMING_SME2"
   "<sve_int_op>\t%0, %0, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_<sve_type_int>")]
 )
 
 (define_insn "@aarch64_sve_<sve_int_op><mode>"
          SVE_INT_BINARY_MULTI))]
   "TARGET_STREAMING_SME2"
   "<sve_int_op>\t%0, %0, %2"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "@aarch64_sve_single_<sve_int_op><mode>"
          SVE_INT_BINARY_MULTI))]
   "TARGET_STREAMING_SME2"
   "<sve_int_op>\t%0, %0, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; -------------------------------------------------------------------------
      [       w,  0, w, w; *             ] <su>clamp\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
      [     ?&w,  w, w, w; yes           ] movprfx\t%0, %1\;<su>clamp\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn_and_split "*aarch64_sve_<su>clamp<mode>_x"
            (match_operand:<VSINGLE> 3 "register_operand" "w"))))]
   "TARGET_STREAMING_SME2"
   "<su>clamp\t%0, %2.<Vetype>, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:SVE_FULL_HSDI_SIMD_DI 1 "register_operand" "w")))]
   "TARGET_SVE2"
   "mul\t%Z0.<Vetype>, %Z1.<Vetype>, %Z2.<Vetype>[%3]"
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; The 2nd and 3rd alternatives are valid for just TARGET_SVE as well but
      [ w        , 0 , vsm ; *              ] mul\t%Z0.<Vetype>, %Z0.<Vetype>, #%2
      [ ?&w      , w , vsm ; yes            ] movprfx\t%Z0, %Z1\;mul\t%Z0.<Vetype>, %Z0.<Vetype>, #%2
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; -------------------------------------------------------------------------
   "@
    sqadd\t%0.<Vetype>, %0.<Vetype>, #%D2
    movprfx\t%0, %1\;sqadd\t%0.<Vetype>, %0.<Vetype>, #%D2"
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; General predicated binary arithmetic.  All operations handled here
      [ w        , Upl , w , 0 ; *              ] <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated binary arithmetic with merging.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated binary arithmetic, merging with the second input.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated binary operations, merging with an independent value.
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Predicated binary operations with no reverse form, merging with zero.
   {
     operands[5] = CONSTM1_RTX (<VPRED>mode);
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_BINARY_LANE))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]"
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , Upl , w , D<lr> ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
      [ ?&w      , Upl , w , w     ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated left shifts with merging.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated left shifts, merging with the second input.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; Predicated left shifts, merging with an independent value.
     else
       FAIL;
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?&w      , Upl , w , w ; yes , *    ] movprfx\t%0, %2\;<b><sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
   [(set_attr "is_bf16" "<is_bf16>")
-   (set_attr "supports_bf16_rev" "<supports_bf16_rev>")]
+   (set_attr "supports_bf16_rev" "<supports_bf16_rev>")
+   (set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; -------------------------------------------------------------------------
      [       w,  0, w, w; *             ] <b>fclamp\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
      [     ?&w,  w, w, w; yes           ] movprfx\t%0, %1\;<b>fclamp\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 (define_insn_and_split "*aarch64_sve_fclamp<mode>_x"
          UNSPEC_FMINNM))]
   "TARGET_STREAMING_SME2"
   "<b>fclamp\t%0, %2.<Vetype>, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; =========================================================================
      [ w        , 0 , w , w ; *              ] <sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "@aarch64_sve_<sve_int_op>_lane_<mode>"
      [ w        , 0 , w , <sve_lane_con> ; *              ] <sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4]
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;<sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4]
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , <sve_lane_con> ; *              ] mla\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4]
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;mla\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4]
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 (define_insn "@aarch64_sve_sub_mul_lane_<mode>"
      [ w        , 0 , w , <sve_lane_con> ; *              ] mls\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4]
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;mls\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4]
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; -------------------------------------------------------------------------
       return "xar\t%Z0.<Vetype>, %Z0.<Vetype>, %Z2.<Vetype>, #%3";
     return "movprfx\t%Z0, %Z1\;xar\t%Z0.<Vetype>, %Z0.<Vetype>, %Z2.<Vetype>, #%3";
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_crypto_sha3")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_crypto_sha3")]
 )
 
 ;; Unpredicated 3-way exclusive OR.
      [ w        , w , w , 0 ; *              ] eor3\t%0.d, %0.d, %1.d, %2.d
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;eor3\t%0.d, %0.d, %2.d, %3.d
   }
+  [(set_attr "sve_type" "sve_crypto_sha3")]
 )
 
 ;; Use NBSL for vector NOR.
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "*aarch64_sve2_unpred_nor<mode>"
      [ w        , 0  , w ; *              ] nbsl\t%Z0.d, %Z0.d, %Z2.d, %Z0.d
      [ ?&w      , w  , w ; yes            ] movprfx\t%Z0, %Z1\;nbsl\t%Z0.d, %Z0.d, %Z2.d, %Z1.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Use NBSL for vector NAND.
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Same as above but unpredicated and including Advanced SIMD modes.
      [ w        , 0  , w ; *              ] nbsl\t%Z0.d, %Z0.d, %Z2.d, %Z2.d
      [ ?&w      , w  , w ; yes            ] movprfx\t%Z0, %Z1\;nbsl\t%Z0.d, %Z0.d, %Z2.d, %Z2.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Unpredicated bitwise select.
      [ w        , <bsl_1st> , <bsl_2nd> , w ; *              ] bsl\t%0.d, %0.d, %<bsl_dup>.d, %3.d
      [ ?&w      , w         , w         , w ; yes            ] movprfx\t%0, %<bsl_mov>\;bsl\t%0.d, %0.d, %<bsl_dup>.d, %3.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Unpredicated bitwise inverted select.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "*aarch64_sve2_nbsl_unpred<mode>"
      [ w        , <bsl_1st> , <bsl_2nd> , w ; *              ] nbsl\t%Z0.d, %Z0.d, %Z<bsl_dup>.d, %Z3.d
      [ ?&w      , w         , w         , w ; yes            ] movprfx\t%Z0, %Z<bsl_mov>\;nbsl\t%Z0.d, %Z0.d, %Z<bsl_dup>.d, %Z3.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Unpredicated bitwise select with inverted first operand.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "*aarch64_sve2_bsl1n_unpred<mode>"
      [ w        , <bsl_1st> , <bsl_2nd> , w ; *              ] bsl1n\t%Z0.d, %Z0.d, %Z<bsl_dup>.d, %Z3.d
      [ ?&w      , w         , w         , w ; yes            ] movprfx\t%Z0, %Z<bsl_mov>\;bsl1n\t%Z0.d, %Z0.d, %Z<bsl_dup>.d, %Z3.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Unpredicated bitwise select with inverted second operand.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Unpredicated bitwise select with inverted second operand, alternative form.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "*aarch64_sve2_bsl2n_unpred<mode>"
      [ w        , <bsl_1st> , <bsl_2nd> , w ; *              ] bsl2n\t%Z0.d, %Z0.d, %Z3.d, %Z<bsl_dup>.d
      [ ?&w      , w         , w         , w ; yes            ] movprfx\t%Z0, %Z<bsl_mov>\;bsl2n\t%Z0.d, %Z0.d, %Z3.d, %Z<bsl_dup>.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "*aarch64_sve2_bsl2n_unpred<mode>"
      [ w        , <bsl_1st> , <bsl_2nd> , w ; *              ] bsl2n\t%Z0.d, %Z0.d, %Z3.d, %Z<bsl_dup>.d
      [ ?&w      , w         , w         , w ; yes            ] movprfx\t%Z0, %Z<bsl_mov>\;bsl2n\t%Z0.d, %Z0.d, %Z3.d, %Z<bsl_dup>.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Vector EON (~(x, y)) using BSL2N.
   {
     operands[3] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "*aarch64_sve2_eon_bsl2n_unpred<mode>"
      [ w  ,      0, w ; *              ] bsl2n\t%Z0.d, %Z0.d, %Z0.d, %Z2.d
      [ ?&w,      w, w ; yes            ] movprfx\t%Z0, %Z1\;bsl2n\t%Z0.d, %Z0.d, %Z1.d, %Z2.d
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w ; *              ] <sra_op>sra\t%0.<Vetype>, %2.<Vetype>, #%3
      [ ?&w      , w , w ; yes            ] movprfx\t%0, %1\;<sra_op>sra\t%0.<Vetype>, %2.<Vetype>, #%3
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; SRSRA and URSRA.
      [ w        , 0 , w ; *              ] <sur>sra\t%0.<Vetype>, %2.<Vetype>, #%3
      [ ?&w      , w , w ; yes            ] movprfx\t%0, %1\;<sur>sra\t%0.<Vetype>, %2.<Vetype>, #%3
   }
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_SHIFT_INSERT))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vetype>, %2.<Vetype>, #%3"
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , w ; *              ] <su>aba\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<su>aba\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_accum")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , w ; *              ] <insn>\t%0.h, %2.b, %3.b
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<insn>\t%0.h, %2.b, %3.b
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "@aarch64_sve_add_<insn><mode>"
      [ w        , 0 , w , w ; *              ] <insn>\t%0.s, %2.b, %3.b
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<insn>\t%0.s, %2.b, %3.b
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "@aarch64_sve_add_lane_<insn><mode>"
      [ w        , 0 , w , y ; *              ] <insn>\t%0.h, %2.b, %3.b[%4]
      [ ?&w      , w , w , y ; yes            ] movprfx\t%0, %1\;<insn>\t%0.h, %2.b, %3.b[%4]
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "@aarch64_sve_add_lane_<insn><mode>"
      [ w        , 0 , w , y ; *              ] <insn>\t%0.s, %2.b, %3.b[%4]
      [ ?&w      , w , w , y ; yes            ] movprfx\t%0, %1\;<insn>\t%0.s, %2.b, %3.b[%4]
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , w ; *              ] fdot\t%0.<Vetype>, %2.b, %3.b
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;fdot\t%0.<Vetype>, %2.b, %3.b
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "@aarch64_sve_dot_lane<mode>"
      [ w        , 0 , w , y ; *              ] fdot\t%0.<Vetype>, %2.b, %3.b[%4]
      [ ?&w      , w , w , y ; yes            ] movprfx\t%0, %1\;fdot\t%0.<Vetype>, %2.b, %3.b[%4]
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; =========================================================================
          (match_operand:SVE_FULL_BHSI 1 "register_operand" "w")))]
   "TARGET_STREAMING_SME2"
   "<su>unpk\t%0, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "<optab><mode><v2xwide>2"
          (match_operand:SVE_FULL_BHSIx2 1 "aligned_register_operand" "Uw2")))]
   "TARGET_STREAMING_SME2"
   "<su>unpk\t%0, %1"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_BINARY_WIDE))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Ventype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_BINARY_LONG))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vetype>, %1.<Ventype>, %2.<Ventype>"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "@aarch64_sve_<sve_int_op>_lane_<mode>"
          SVE2_INT_BINARY_LONG_LANE))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vetype>, %1.<Ventype>, %2.<Ventype>[%3]"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_SHIFT_IMM_LONG))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vetype>, %1.<Ventype>, #%2"
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , 0 , w , w ; *              ] <sve_int_add_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_add_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Non-saturating MLA operations with lane select.
      [ w        , 0 , w , <sve_lane_con> ; *              ] <sve_int_add_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;<sve_int_add_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Saturating MLA operations.
      [ w        , 0 , w , w ; *              ] <sve_int_qadd_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_qadd_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Saturating MLA operations with lane select.
      [ w        , 0 , w , <sve_lane_con> ; *              ] <sve_int_qadd_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;<sve_int_qadd_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Non-saturating MLS operations.
      [ w        , 0 , w , w ; *              ] <sve_int_sub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_sub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Non-saturating MLS operations with lane select.
      [ w        , 0 , w , <sve_lane_con> ; *              ] <sve_int_sub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;<sve_int_sub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Saturating MLS operations.
      [ w        , 0 , w , w ; *              ] <sve_int_qsub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_qsub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Saturating MLS operations with lane select.
      [ w        , 0 , w , <sve_lane_con> ; *              ] <sve_int_qsub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;<sve_int_qsub_op>\t%0.<Vetype>, %2.<Ventype>, %3.<Ventype>[%4]
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Two-way dot-product.
      [ w        , w , w , 0 ; *              ] <sur>dot\t%0.s, %1.h, %2.h
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %3\;<sur>dot\t%0.s, %1.h, %2.h
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE_FP_BINARY_MULTI))]
   "TARGET_STREAMING_SME2"
   "<b><maxmin_uns_op>\t%0, %0, %2"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "@aarch64_sve_single_<maxmin_uns_op><mode>"
          SVE_FP_BINARY_MULTI))]
   "TARGET_STREAMING_SME2"
   "<b><maxmin_uns_op>\t%0, %0, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , w , w , 0 ; *              ] <sve_fp_op>\t%0.<Vetype>, %1.<Ventype>, %2.<Ventype>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %3\;<sve_fp_op>\t%0.<Vetype>, %1.<Ventype>, %2.<Ventype>
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 (define_insn "@aarch64_<sve_fp_op>_lane_<mode>"
      [ w        , w , <sve_lane_con> , 0 ; *              ] <sve_fp_op>\t%0.<Vetype>, %1.<Ventype>, %2.<Ventype>[%3]
      [ ?&w      , w , <sve_lane_con> , w ; yes            ] movprfx\t%0, %4\;<sve_fp_op>\t%0.<Vetype>, %1.<Ventype>, %2.<Ventype>[%3]
   }
+  [(set_attr "sve_type" "sve_<sve_type_unspec>")]
 )
 
 ;; Two-way dot-product.
      [ w        , w , w , 0 ; *              ] fdot\t%0.s, %1.h, %2.h
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %3\;fdot\t%0.s, %1.h, %2.h
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 (define_insn "aarch64_fdot_prod_lanevnx4sfvnx8hf"
      [ w        , w , y , 0 ; *              ] fdot\t%0.s, %1.h, %2.h[%3]
      [ ?&w      , w , y , w ; yes            ] movprfx\t%0, %4\;fdot\t%0.s, %1.h, %2.h[%3]
   }
+  [(set_attr "sve_type" "sve_fp_mul")]
 )
 
 ;; =========================================================================
          SVE2_INT_UNARY_NARROWB))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Ventype>, %1.<Vetype>"
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 ;; These instructions do not take MOVPRFX.
          SVE2_INT_UNARY_NARROWT))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Ventype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE_QCVTxN))]
   "TARGET_STREAMING_SME2"
   "<optab>\t%0.b, %1"
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 (define_insn "@aarch64_sve_<optab><VNx8HI_ONLY:mode><VNx8SI_ONLY:mode>"
          SVE_QCVTxN))]
   ""
   "<optab>\t%0.h, %1"
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 (define_insn "@aarch64_sve_<optab><VNx8HI_ONLY:mode><VNx8DI_ONLY:mode>"
          SVE_QCVTxN))]
   "TARGET_STREAMING_SME2"
   "<optab>\t%0.h, %1"
+  [(set_attr "sve_type" "sve_int_extract")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_BINARY_NARROWB))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Ventype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; These instructions do not take MOVPRFX.
          SVE2_INT_BINARY_NARROWT))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Ventype>, %2.<Vetype>, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; Optimize ((a + b) >> n) where n is half the bitsize of the vector
            "aarch64_simd_shift_imm_vec_exact_top" "")))]
   "TARGET_SVE2"
   "addhnb\t%0.<Ventype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_SHIFT_IMM_NARROWB))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Ventype>, %1.<Vetype>, #%2"
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; The immediate range is enforced before generating the instruction.
          SVE2_INT_SHIFT_IMM_NARROWT))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Ventype>, %2.<Vetype>, #%3"
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_SHIFT_IMM_NARROWxN))]
   "(<MODE>mode == VNx8SImode || TARGET_STREAMING_SME2)"
   "<sve_int_op>\t%0.<Ventype>, %1, #%2"
+  [(set_attr "sve_type" "sve_int_shift")]
 )
 
 ;; =========================================================================
      [ w        , Upl , 0 , w ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0 , w ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
      [ ?&w      , Upl , w , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; -------------------------------------------------------------------------
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_accum")]
 )
 
 ;; Predicated pairwise absolute difference and accumulate, merging with zero.
   {
     operands[5] = CONSTM1_RTX (<VPRED>mode);
   }
-  [(set_attr "movprfx" "yes")]
+  [(set_attr "movprfx" "yes")
+   (set_attr "sve_type" "sve_int_accum")]
 )
 
 ;; -------------------------------------------------------------------------
     operands[5] = copy_rtx (operands[1]);
     operands[6] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_arith")]
 )
 
 ;; =========================================================================
      [ w        , 0 , w ; *              ] <sve_int_op>\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #<rot>
      [ ?&w      , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_op>\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #<rot>
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; unpredicated optab pattern for auto-vectorizer
      [ w        , 0 , w , w ; *              ] <sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>, #<rot>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>, #<rot>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 (define_insn "@aarch64_<optab>_lane_<mode>"
      [ w        , 0 , w , <sve_lane_con> ; *              ] <sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4], #<rot>
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;<sve_int_op>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>[%4], #<rot>
   }
+  [(set_attr "sve_type" "sve_int_mul")]
 )
 
 ;; unpredicated optab pattern for auto-vectorizer
      [ w        , 0 , w , w ; *              ] <sve_int_op>\t%0.<Vetype>, %2.<Vetype_fourth>, %3.<Vetype_fourth>, #<rot>
      [ ?&w      , w , w , w ; yes            ] movprfx\t%0, %1\;<sve_int_op>\t%0.<Vetype>, %2.<Vetype_fourth>, %3.<Vetype_fourth>, #<rot>
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 (define_insn "@aarch64_<optab>_lane_<mode>"
      [ w        , 0 , w , <sve_lane_con> ; *              ] <sve_int_op>\t%0.<Vetype>, %2.<Vetype_fourth>, %3.<Vetype_fourth>[%4], #<rot>
      [ ?&w      , w , w , <sve_lane_con> ; yes            ] movprfx\t%0, %1\;<sve_int_op>\t%0.<Vetype>, %2.<Vetype_fourth>, %3.<Vetype_fourth>[%4], #<rot>
   }
+  [(set_attr "sve_type" "sve_int_dot")]
 )
 
 ;; =========================================================================
          SVE2_COND_FP_UNARY_LONG))]
   "TARGET_SVE2"
   "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Ventype>"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated convert long top with merging.
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "*cond_<sve_fp_op><mode>_strict"
          UNSPEC_SEL))]
   "TARGET_SVE2"
   "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Ventype>"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "@aarch64_sve2_fp8_cvt_<fp8_cvt_uns_op><mode>"
          FP8CVT_UNS))]
   "TARGET_SSVE_FP8"
   "<b><fp8_cvt_uns_op>\t%0.h, %1.b"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_COND_FCVTNT))]
   "TARGET_SVE2"
   "fcvtnt\t%0.<Vetype>, %2/m, %3.<Vewtype>"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated FCVTX (equivalent to what would be FCVTXNB, except that
      [ w        , Upl , 0 ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vewtype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vewtype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated FCVTX with merging.
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "*cond_<sve_fp_op><mode>_any_strict"
      [ &w       , Upl , w , Dz ; yes            ] movprfx\t%0.<Vewtype>, %1/z, %2.<Vewtype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vewtype>
      [ &w       , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vewtype>
   }
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; Predicated FCVTXNT.  This doesn't give a natural aarch64_pred_*/cond_*
          UNSPEC_COND_FCVTXNT))]
   "TARGET_SVE2"
   "fcvtxnt\t%0.<Ventype>, %2/m, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:VNx8HF 1 "register_operand" "w")))]
   "TARGET_STREAMING_SME_F16F16"
   "fcvt\t%0, %1.h"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "@aarch64_sve_cvtl<mode>"
          UNSPEC_FCVTL))]
   "TARGET_STREAMING_SME_F16F16"
   "fcvtl\t%0, %1.h"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:VNx8SF 1 "aligned_register_operand" "Uw2")))]
   "TARGET_STREAMING_SME2"
   "<b>fcvt\t%0.h, %1"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "@aarch64_sve_cvtn<mode>"
          UNSPEC_FCVTN))]
   "TARGET_STREAMING_SME2"
   "<b>fcvtn\t%0.h, %1"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "@aarch64_sve2_fp8_cvtn<mode>"
          UNSPEC_FP8FCVTN))]
   "TARGET_SSVE_FP8"
   "<b>fcvtn\t%0.b, %1"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "@aarch64_sve2_fp8_cvtnb<mode>"
          UNSPEC_FCVTNB))]
   "TARGET_SSVE_FP8"
   "fcvtnb\t%0.b, %1"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 (define_insn "@aarch64_sve_cvtnt<mode>"
          UNSPEC_FCVTNT))]
   "TARGET_SSVE_FP8"
   "fcvtnt\t%0.b, %2"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:<V_INT_EQUIV> 1 "aligned_register_operand" "Uw<vector_count>")))]
   "TARGET_STREAMING_SME2"
   "<su_optab>cvtf\t%0, %1"
+  [(set_attr "sve_type" "sve_int_cvt")]
 )
 
 ;; -------------------------------------------------------------------------
          (match_operand:SVE_SFx24 1 "aligned_register_operand" "Uw<vector_count>")))]
   "TARGET_STREAMING_SME2"
   "fcvtz<su>\t%0, %1"
+  [(set_attr "sve_type" "sve_fp_cvt")]
 )
 
 ;; =========================================================================
      [ w        , Upl , 0 ; *              ] <sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_int_recip_est")]
 )
 
 ;; Predicated integer unary operations with merging.
   {
     operands[4] = CONSTM1_RTX (<VPRED>mode);
   }
+  [(set_attr "sve_type" "sve_int_recip_est")]
 )
 
 ;; -------------------------------------------------------------------------
      [ w        , Upl , 0 ; *              ] <sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_log")]
 )
 
 ;; Predicated FLOGB with merging.
   {
     operands[4] = copy_rtx (operands[1]);
   }
+  [(set_attr "sve_type" "sve_fp_log")]
 )
 
 (define_insn "*cond_<sve_fp_op><mode>_strict"
      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
   }
+  [(set_attr "sve_type" "sve_fp_log")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_PMUL))]
   "TARGET_SVE2"
   "pmul\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_pmul")]
 )
 
 ;; Extending PMUL, with the results modeled as wider vectors.
          SVE2_PMULL))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vetype>, %1.<Ventype>, %2.<Ventype>"
+  [(set_attr "sve_type" "sve_int_pmul")]
 )
 
 ;; Extending PMUL, with the results modeled as pairs of values.
          SVE2_PMULL_PAIR))]
   "TARGET_SVE2"
   "<sve_int_op>\t%0.<Vewtype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_pmul")]
 )
 
 ;; =========================================================================
          UNSPEC_SEL))]
   "TARGET_STREAMING_SME2"
   "sel\t%0, %K3, %1, %2"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
    (clobber (reg:CC_NZC CC_REGNUM))]
   "TARGET_SVE2p1_OR_SME2"
   "while<cmp_op>\t{%S0.<bits_etype>, %T0.<bits_etype>}, %x1, %x2"
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 (define_insn "@aarch64_sve_while<while_optab_cmp>_c<BHSD_BITS>"
    (clobber (reg:CC_NZC CC_REGNUM))]
   "TARGET_SVE2p1_OR_SME2"
   "while<cmp_op>\t%K0.<bits_etype>, %x1, %x2, vlx%3"
+  [(set_attr "sve_type" "sve_pred_cnt_ctrl")]
 )
 
 ;; =========================================================================
          SVE_INT_REDUCTION_128))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "<optab>\t%0.<Vtype>, %1, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_reduc")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE_FP_REDUCTION_128))]
   "TARGET_SVE2p1 && TARGET_NON_STREAMING"
   "<optab>\t%0.<Vtype>, %1, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_fp_reduc")]
 )
 
 ;; =========================================================================
      [ w        , Upl , 0 ; *              ] revd\t%0.q, %1/m, %2.q
      [ ?&w      , Upl , w ; yes            ] movprfx\t%0, %2\;revd\t%0.q, %1/m, %2.q
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "@cond_<optab><mode>"
      [ w        , Upl , w , 0  ; *              ] revd\t%0.q, %1/m, %2.q
      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;revd\t%0.q, %1/m, %2.q
   }
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
    && TARGET_NON_STREAMING
    && IN_RANGE (INTVAL (operands[2]) * (<elem_bits> / 8), 0, 15)"
   "dupq\t%0.<Vetype>, %1.<Vetype>[%2]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "@aarch64_sve_extq<mode>"
            ? "extq\\t%0.b, %0.b, %2.b, #%3"
            : "movprfx\t%0, %1\;extq\\t%0.b, %0.b, %2.b, #%3");
   }
-  [(set_attr "movprfx" "*,yes")]
+  [(set_attr "movprfx" "*,yes")
+   (set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          UNSPEC_TBL2))]
   "TARGET_SVE2"
   "tbl\t%0.<Vetype>, %1, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; TBX(Q).  These instructions do not take MOVPRFX.
          SVE_TBX))]
   "TARGET_SVE2"
   "<perm_insn>\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_x24_PERMUTE))]
   "TARGET_STREAMING_SME2"
   "<perm_insn>\t%0, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "@aarch64_sve_<optab><mode>"
          SVE2_x24_PERMUTEQ))]
   "TARGET_STREAMING_SME2"
   "<perm_insn>\t{%S0.q - %T0.q}, %1.q, %2.q"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "@aarch64_sve_<optab><mode>"
          SVE2_x24_PERMUTE))]
   "TARGET_STREAMING_SME2"
   "<perm_insn>\t%0, %1"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "@aarch64_sve_<optab><mode>"
          SVE2_x24_PERMUTEQ))]
   "TARGET_STREAMING_SME2"
   "<perm_insn>\t{%S0.q - %V0.q}, {%S1.q - %V1.q}"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
          SVE2_INT_BITPERM))]
   "TARGET_SVE2_BITPERM"
   "<sve_int_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_bit_perm")]
 )
 
 ;; =========================================================================
          UNSPEC_HISTCNT))]
   "TARGET_SVE2 && TARGET_NON_STREAMING"
   "histcnt\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "@aarch64_sve2_histseg<mode>"
          UNSPEC_HISTSEG))]
   "TARGET_SVE2 && TARGET_NON_STREAMING"
   "histseg\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; -------------------------------------------------------------------------
      [ ?Upl    , 0  , w, w; yes                 ] ^
      [ Upa     , Upl, w, w; no                  ] ^
   }
+  [(set_attr "sve_type" "sve_int_match")]
 )
 
 (define_expand "@aarch64_pred_<sve_int_op><mode>"
     operands[6] = copy_rtx (operands[4]);
     operands[7] = operands[5];
   }
+  [(set_attr "sve_type" "sve_int_match")]
 )
 
 (define_insn_and_rewrite "*aarch64_pred_<sve_int_op><mode>_cc"
     operands[6] = copy_rtx (operands[4]);
     operands[7] = operands[5];
   }
+  [(set_attr "sve_type" "sve_int_match")]
 )
 
 ;; -------------------------------------------------------------------------
         UNSPEC_SVE_LUTI))]
   "TARGET_LUT && TARGET_SVE2_OR_SME2"
   "luti<LUTI_BITS>\t%0.<Vetype>, { %1.<Vetype> }, %2[%3]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 (define_insn "@aarch64_sve_luti<LUTI_BITS><mode>"
          UNSPEC_SVE_LUTI))]
   "TARGET_LUT && TARGET_SVE2_OR_SME2"
   "luti<LUTI_BITS>\t%0.<Vetype>, %1, %2[%3]"
+  [(set_attr "sve_type" "sve_int_general")]
 )
 
 ;; =========================================================================
index ca612dac600a15eedd5ed5872216b54ccde8d34d..36363e8f7c512b160b96b988bb95e87950172c05 100644 (file)
 ;; patterns.
 (define_attr "ldpstp" "ldp,stp,none" (const_string "none"))
 
+;; Attribute that classifies SVE instructions by their functional type.
+;; This attribute is currently only used for dispatch scheduling.
+(define_attr "sve_type"
+  "none,\
+   sve_pred_logical,sve_pred_cnt_ctrl,sve_pred_cnt_scalar,sve_pred_misc,\
+   sve_pred_vec,\
+   sve_fp_arith,sve_fp_mul,sve_fp_assoc_add,sve_fp_cmp,sve_fp_cvt,sve_fp_log,\
+   sve_fp_exp,sve_fp_div,sve_fp_sqrt,sve_fp_reduc,sve_fp_misc,\
+   sve_int_general,sve_int_shift,sve_int_mul,sve_int_dot,sve_int_cmp_set,\
+   sve_int_extend,sve_int_extract,sve_int_cvt,sve_int_div,sve_int_index,\
+   sve_int_match,sve_int_recip_est,sve_int_reduc,sve_int_accum,\
+   sve_int_pmul,sve_int_bit_perm,\
+   sve_load_pred,sve_load_1reg,sve_load_2reg,sve_load_3reg,sve_load_4reg,\
+   sve_gatherload_32,sve_gatherload_64,\
+   sve_store_pred,sve_store_1reg,sve_store_2reg,sve_store_3reg,sve_store_4reg,\
+   sve_scatterstore_32,sve_scatterstore_64,\
+   sve_ffr,\
+   sve_crypto_sha3"
+  (const_string "none"))
+
 ;; -------------------------------------------------------------------
 ;; Pipeline descriptions and scheduling
 ;; -------------------------------------------------------------------
index 451b00f55af5a21146a4505451a68bd2dc408e8e..332e7ffd2eaf6597f7bce9c22df70a72ebfe8164 100644 (file)
                                  (UNSPEC_SQDMULLBT "sqdmlslbt")
                                  (UNSPEC_SQDMULLT "sqdmlslt")])
 
+;; The value of the attribute "sve_type" associated with an unspec.
+(define_int_attr sve_type_unspec [(UNSPEC_COND_FABS "fp_arith")
+                                 (UNSPEC_COND_FNEG "fp_arith")
+                                 (UNSPEC_FRECPE "fp_log")
+                                 (UNSPEC_COND_FRECPX "fp_log")
+                                 (UNSPEC_COND_FRINTA "fp_cvt")
+                                 (UNSPEC_COND_FRINTI "fp_cvt")
+                                 (UNSPEC_COND_FRINTM "fp_cvt")
+                                 (UNSPEC_COND_FRINTN "fp_cvt")
+                                 (UNSPEC_COND_FRINTP "fp_cvt")
+                                 (UNSPEC_COND_FRINTX "fp_cvt")
+                                 (UNSPEC_COND_FRINTZ "fp_cvt")
+                                 (UNSPEC_RSQRTE "fp_log")
+                                 (UNSPEC_COND_FSQRT "fp_sqrt")
+                                 (UNSPEC_FRECPS "fp_mul")
+                                 (UNSPEC_RSQRTS "fp_mul")
+                                 (UNSPEC_COND_FDIV "fp_div")
+                                 (UNSPEC_COND_FMULX "fp_mul")
+                                 (UNSPEC_COND_FAMAX "fp_arith")
+                                 (UNSPEC_COND_FAMIN "fp_arith")
+                                 (UNSPEC_COND_FADD "fp_arith")
+                                 (UNSPEC_COND_FMAX "fp_arith")
+                                 (UNSPEC_COND_FMAXNM "fp_arith")
+                                 (UNSPEC_COND_FMIN "fp_arith")
+                                 (UNSPEC_COND_FMINNM "fp_arith")
+                                 (UNSPEC_COND_FMUL "fp_mul")
+                                 (UNSPEC_COND_FSUB "fp_arith")
+                                 (UNSPEC_FMLALB "fp_mul")
+                                 (UNSPEC_FMLALT "fp_mul")
+                                 (UNSPEC_FMLSLB "fp_mul")
+                                 (UNSPEC_FMLSLT "fp_mul")
+                                 (UNSPEC_FMAX "fp_arith")
+                                 (UNSPEC_FMAXNM "fp_arith")
+                                 (UNSPEC_FMIN "fp_arith")
+                                 (UNSPEC_FMINNM "fp_arith")
+                                 (UNSPEC_FDOT "fp_mul")
+                                 (UNSPEC_COND_SMAX "fp_arith")
+                                 (UNSPEC_COND_SMIN "fp_arith")
+                                 (UNSPEC_ADCLB "int_general")
+                                 (UNSPEC_ADCLT "int_general")
+                                 (UNSPEC_EORBT "int_general")
+                                 (UNSPEC_EORTB "int_general")
+                                 (UNSPEC_SBCLB "int_general")
+                                 (UNSPEC_SBCLT "int_general")
+                                 (UNSPEC_SQRDMLAH "int_mul")
+                                 (UNSPEC_SQRDMLSH "int_mul")
+                                 (UNSPEC_SABDLB "int_general")
+                                 (UNSPEC_SABDLT "int_general")
+                                 (UNSPEC_SADDLB "int_general")
+                                 (UNSPEC_SADDLBT "int_general")
+                                 (UNSPEC_SADDLT "int_general")
+                                 (UNSPEC_SMULLB "int_mul")
+                                 (UNSPEC_SMULLT "int_mul")
+                                 (UNSPEC_SQDMULLB "int_mul")
+                                 (UNSPEC_SQDMULLBT "int_mul")
+                                 (UNSPEC_SQDMULLT "int_mul")
+                                 (UNSPEC_SSUBLB "int_general")
+                                 (UNSPEC_SSUBLBT "int_general")
+                                 (UNSPEC_SSUBLT "int_general")
+                                 (UNSPEC_SSUBLTB "int_general")
+                                 (UNSPEC_UABDLB "int_general")
+                                 (UNSPEC_UABDLT "int_general")
+                                 (UNSPEC_UADDLB "int_general")
+                                 (UNSPEC_UADDLT "int_general")
+                                 (UNSPEC_UMULLB "int_mul")
+                                 (UNSPEC_UMULLT "int_mul")
+                                 (UNSPEC_USUBLB "int_general")
+                                 (UNSPEC_USUBLT "int_general")
+                                 (UNSPEC_SQDMULH "int_mul")
+                                 (UNSPEC_URSHL "int_shift")
+                                 (UNSPEC_SRSHL "int_shift")])
+
+;; The value of the attribute "sve_type" associated with an int code.
+(define_code_attr sve_type_int [(mult "int_mul")
+                               (smax "int_general")
+                               (smin "int_general")
+                               (umax "int_general")
+                               (umin "int_general")
+                               (plus "int_general")
+                               (minus "int_general")
+                               (ashift "int_shift")
+                               (ashiftrt "int_shift")
+                               (lshiftrt "int_shift")
+                               (and "int_general")
+                               (ior "int_general")
+                               (xor "int_general")
+                               (ss_plus "int_general")
+                               (us_plus "int_general")
+                               (ss_minus "int_general")
+                               (us_minus "int_general")])
+
+;; The value of the attribute "sve_type" associated with an fp code.
+(define_code_attr sve_type_fp [(mult "fp_mul")
+                              (plus "fp_arith")
+                              (minus "fp_arith")])
+
 (define_int_attr sve_fp_op [(UNSPEC_BFDOT "bfdot")
                            (UNSPEC_BFMLALB "bfmlalb")
                            (UNSPEC_BFMLALT "bfmlalt")