RISC-V: Normalize SEW = 64 handling into a simplified function
authorJu-Zhe Zhong <juzhe.zhong@rivai.ai>
Wed, 15 Feb 2023 08:39:54 +0000 (16:39 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Fri, 17 Feb 2023 02:46:35 +0000 (10:46 +0800)
Co-authored-by: kito-cheng <kito.cheng@sifive.com>
gcc/ChangeLog:

* config/riscv/riscv-protos.h (sew64_scalar_helper): New function.
* config/riscv/riscv-v.cc (has_vi_variant_p): Adjust.
(sew64_scalar_helper): New function.
* config/riscv/vector.md: Normalization.

Co-authored-by: kito-cheng <kito.cheng@sifive.com>
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv-v.cc
gcc/config/riscv/vector.md

index 81ad2ea..37c634e 100644 (file)
@@ -181,6 +181,8 @@ bool neg_simm5_p (rtx);
 #ifdef RTX_CODE
 bool has_vi_variant_p (rtx_code, rtx);
 #endif
+bool sew64_scalar_helper (rtx *, rtx *, rtx, machine_mode, machine_mode,
+                         bool, void (*)(rtx *, rtx));
 }
 
 /* We classify builtin types into two classes:
index dd70bf9..59c25c6 100644 (file)
@@ -418,14 +418,11 @@ has_vi_variant_p (rtx_code code, rtx x)
   switch (code)
     {
     case PLUS:
-    case MINUS:
     case AND:
     case IOR:
     case XOR:
     case SS_PLUS:
-    case SS_MINUS:
     case US_PLUS:
-    case US_MINUS:
     case EQ:
     case NE:
     case LE:
@@ -438,10 +435,53 @@ has_vi_variant_p (rtx_code code, rtx x)
     case LTU:
     case GE:
     case GEU:
+    case MINUS:
+    case SS_MINUS:
       return neg_simm5_p (x);
+
     default:
       return false;
     }
 }
 
+bool
+sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl,
+                    machine_mode vector_mode, machine_mode mask_mode,
+                    bool has_vi_variant_p,
+                    void (*emit_vector_func) (rtx *, rtx))
+{
+  machine_mode scalar_mode = GET_MODE_INNER (vector_mode);
+  if (has_vi_variant_p)
+    {
+      *scalar_op = force_reg (scalar_mode, *scalar_op);
+      return false;
+    }
+
+  if (TARGET_64BIT)
+    {
+      if (!rtx_equal_p (*scalar_op, const0_rtx))
+       *scalar_op = force_reg (scalar_mode, *scalar_op);
+      return false;
+    }
+
+  if (immediate_operand (*scalar_op, Pmode))
+    {
+      if (!rtx_equal_p (*scalar_op, const0_rtx))
+       *scalar_op = force_reg (Pmode, *scalar_op);
+
+      *scalar_op = gen_rtx_SIGN_EXTEND (scalar_mode, *scalar_op);
+      return false;
+    }
+
+  if (CONST_INT_P (*scalar_op))
+    *scalar_op = force_reg (scalar_mode, *scalar_op);
+
+  rtx tmp = gen_reg_rtx (vector_mode);
+  riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (vector_mode), tmp,
+                                 *scalar_op, vl, mask_mode);
+  emit_vector_func (operands, tmp);
+
+  return true;
+}
+
 } // namespace riscv_vector
index 6c02cf3..c897a36 100644 (file)
         (match_operand:VI_D 2 "register_operand"))
       (match_operand:VI_D 1 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::simm5_p (operands[3]))
-      operands[3] = force_reg (<VEL>mode, operands[3]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[3], Pmode))
-         operands[3] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[3]));
-       else
-         {
-           if (CONST_INT_P (operands[3]))
-             operands[3] = force_reg (<VEL>mode, operands[3]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[3], operands[5], <VM>mode);
-           emit_insn (gen_pred_merge<mode> (operands[0], operands[1],
-                       operands[2], v, operands[4],operands[5],
-                       operands[6], operands[7]));
-           DONE;
-         }
-      }
-    else
-      operands[3] = force_reg (<VEL>mode, operands[3]);
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[3],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::simm5_p (operands[3]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_merge<mode> (operands[0], operands[1],
+              operands[2], boardcast_scalar, operands[4], operands[5],
+              operands[6], operands[7]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_merge<mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"     "=vd")
            (match_operand:VI_D 3 "register_operand"))
          (match_operand:VI_D 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::has_vi_variant_p (<CODE>, operands[4]))
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[4], Pmode))
-         {
-           if (!rtx_equal_p (operands[4], const0_rtx))
-             operands[4] = force_reg (Pmode, operands[4]);
-           operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[4]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[4]))
-             operands[4] = force_reg (<VEL>mode, operands[4]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[4], operands[5], <VM>mode);
-           emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
-                       operands[2], operands[3], v, operands[5],
-                       operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      {
-       if (!rtx_equal_p (operands[4], const0_rtx))
-         operands[4] = force_reg (<VEL>mode, operands[4]);
-      }
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[4],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::has_vi_variant_p (<CODE>, operands[4]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
+              operands[2], operands[3], boardcast_scalar, operands[5],
+              operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_<optab><mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
              (match_operand:<VEL> 4 "reg_or_int_operand")))
          (match_operand:VI_D 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::has_vi_variant_p (<CODE>, operands[4]))
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[4], Pmode))
-         {
-           if (!rtx_equal_p (operands[4], const0_rtx))
-             operands[4] = force_reg (Pmode, operands[4]);
-           operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[4]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[4]))
-             operands[4] = force_reg (<VEL>mode, operands[4]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[4], operands[5], <VM>mode);
-           emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
-                       operands[2], operands[3], v, operands[5],
-                       operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      {
-       if (!rtx_equal_p (operands[4], const0_rtx))
-         operands[4] = force_reg (<VEL>mode, operands[4]);
-      }
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[4],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::has_vi_variant_p (<CODE>, operands[4]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
+              operands[2], operands[3], boardcast_scalar, operands[5],
+              operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_<optab><mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
            (match_operand:VI_D 3 "register_operand"))
          (match_operand:VI_D 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::neg_simm5_p (operands[4]))
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[4], Pmode))
-         operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[4]));
-       else
-         {
-           if (CONST_INT_P (operands[4]))
-             operands[4] = force_reg (<VEL>mode, operands[4]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[4], operands[5], <VM>mode);
-           emit_insn (gen_pred_sub<mode> (operands[0], operands[1],
-                       operands[2], operands[3], v, operands[5],
-                       operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[4],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::neg_simm5_p (operands[4]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_sub<mode> (operands[0], operands[1],
+              operands[2], operands[3], boardcast_scalar, operands[5],
+              operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_sub<mode>_reverse_scalar"
   [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
             (match_operand:VFULLI_D 3 "register_operand")] VMULH)
          (match_operand:VFULLI_D 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[4], Pmode))
-         {
-           if (!rtx_equal_p (operands[4], const0_rtx))
-             operands[4] = force_reg (Pmode, operands[4]);
-           operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[4]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[4]))
-             operands[4] = force_reg (<VEL>mode, operands[4]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[4], operands[5], <VM>mode);
-           emit_insn (gen_pred_mulh<v_su><mode> (operands[0], operands[1],
-                       operands[2], operands[3], v, operands[5],
-                       operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      {
-       if (!rtx_equal_p (operands[4], const0_rtx))
-         operands[4] = force_reg (<VEL>mode, operands[4]);
-      }
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[4],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       false,
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_mulh<v_su><mode> (operands[0], operands[1],
+              operands[2], operands[3], boardcast_scalar, operands[5],
+              operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_mulh<v_su><mode>_scalar"
   [(set (match_operand:VFULLI_D 0 "register_operand"       "=vd, vr")
              (match_operand:<VM> 4 "register_operand")] UNSPEC_VADC)
          (match_operand:VI_D 1 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::simm5_p (operands[3]))
-      operands[3] = force_reg (<VEL>mode, operands[3]);
-    else if (!TARGET_64BIT)
-      {
-        rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[3], Pmode))
-         operands[3] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[3]));
-        else
-         {
-           if (CONST_INT_P (operands[3]))
-             operands[3] = force_reg (<VEL>mode, operands[3]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                                           v, operands[3], operands[5],
-                                           <VM>mode);
-           emit_insn (gen_pred_adc<mode> (operands[0], operands[1], operands[2],
-                                          v, operands[4], operands[5],
-                                          operands[6], operands[7]));
-           DONE;
-         }
-      }
-    else
-      operands[3] = force_reg (<VEL>mode, operands[3]);
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[3],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::simm5_p (operands[3]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_adc<mode> (operands[0], operands[1],
+              operands[2], boardcast_scalar, operands[4], operands[5],
+              operands[6], operands[7]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_adc<mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"           "=&vr")
          (unspec:VI_D
             [(plus:VI_D
                (vec_duplicate:VI_D
-                 (match_operand:<VEL> 3 "register_operand" "  r"))
+                 (match_operand:<VEL> 3 "reg_or_0_operand" " rJ"))
                (match_operand:VI_D 2 "register_operand"    " vr"))
              (match_operand:<VM> 4 "register_operand"      " vm")] UNSPEC_VADC)
          (match_operand:VI_D 1 "vector_merge_operand"      "0vu")))]
   "TARGET_VECTOR"
-  "vadc.vxm\t%0,%2,%3,%4"
+  "vadc.vxm\t%0,%2,%z3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
    (set_attr "merge_op_idx" "1")
             [(plus:VI_D
                (vec_duplicate:VI_D
                  (sign_extend:<VEL>
-                   (match_operand:<VSUBEL> 3 "register_operand" "  r")))
+                   (match_operand:<VSUBEL> 3 "reg_or_0_operand" " rJ")))
                (match_operand:VI_D 2 "register_operand"         " vr"))
              (match_operand:<VM> 4 "register_operand"           " vm")] UNSPEC_VADC)
          (match_operand:VI_D 1 "vector_merge_operand"           "0vu")))]
   "TARGET_VECTOR"
-  "vadc.vxm\t%0,%2,%3,%4"
+  "vadc.vxm\t%0,%2,%z3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
    (set_attr "merge_op_idx" "1")
              (match_operand:<VM> 4 "register_operand")] UNSPEC_VSBC)
          (match_operand:VI_D 1 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (!TARGET_64BIT)
-      {
-        rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[3], Pmode))
-         {
-           if (!rtx_equal_p (operands[3], const0_rtx))
-             operands[3] = force_reg (Pmode, operands[3]);
-           operands[3] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[3]);
-         }
-        else
-         {
-           if (CONST_INT_P (operands[3]))
-             operands[3] = force_reg (<VEL>mode, operands[3]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                                           v, operands[3], operands[5],
-                                           <VM>mode);
-           emit_insn (gen_pred_sbc<mode> (operands[0], operands[1], operands[2],
-                                          v, operands[4], operands[5],
-                                          operands[6], operands[7]));
-           DONE;
-         }
-      }
-    else
-      {
-       if (!rtx_equal_p (operands[3], const0_rtx))
-         operands[3] = force_reg (<VEL>mode, operands[3]);
-      }
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[3],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       false,
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_sbc<mode> (operands[0], operands[1],
+              operands[2], boardcast_scalar, operands[4], operands[5],
+              operands[6], operands[7]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_sbc<mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"           "=&vr")
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::simm5_p (operands[2]))
-      operands[2] = force_reg (<VEL>mode, operands[2]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[2], Pmode))
-         operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[2]));
-       else
-         {
-           if (CONST_INT_P (operands[2]))
-             operands[2] = force_reg (<VEL>mode, operands[2]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                                           v, operands[2], operands[5],
-                                           <VM>mode);
-           emit_insn (gen_pred_madc<mode> (operands[0], operands[1], v, operands[3],
-                                           operands[4], operands[5]));
-           DONE;
-         }
-      }
-    else
-      operands[2] = force_reg (<VEL>mode, operands[2]);
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[2],
+       /* vl */operands[4],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::simm5_p (operands[2]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_madc<mode> (operands[0], operands[1],
+              boardcast_scalar, operands[3], operands[4], operands[5]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_madc<mode>_scalar"
   [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
        (unspec:<VM>
           [(plus:VI_D
             (vec_duplicate:VI_D
-              (match_operand:<VEL> 2 "register_operand" "   r"))
+              (match_operand:<VEL> 2 "reg_or_0_operand" "  rJ"))
             (match_operand:VI_D 1 "register_operand"    "  vr"))
            (match_operand:<VM> 3 "register_operand"     "  vm")
            (unspec:<VM>
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
   "TARGET_VECTOR"
-  "vmadc.vxm\t%0,%1,%2,%3"
+  "vmadc.vxm\t%0,%1,%z2,%3"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
    (set_attr "vl_op_idx" "4")
           [(plus:VI_D
             (vec_duplicate:VI_D
               (sign_extend:<VEL>
-                (match_operand:<VSUBEL> 2 "register_operand" "   r")))
+                (match_operand:<VSUBEL> 2 "reg_or_0_operand" "  rJ")))
             (match_operand:VI_D 1 "register_operand"         "  vr"))
            (match_operand:<VM> 3 "register_operand"          "  vm")
            (unspec:<VM>
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
   "TARGET_VECTOR"
-  "vmadc.vxm\t%0,%1,%2,%3"
+  "vmadc.vxm\t%0,%1,%z2,%3"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
    (set_attr "vl_op_idx" "4")
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMSBC))]
   "TARGET_VECTOR"
-  {
-    if (!TARGET_64BIT)
-      {
-        rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[2], Pmode))
-         {
-           if (!rtx_equal_p (operands[2], const0_rtx))
-             operands[2] = force_reg (Pmode, operands[2]);
-           operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[2]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[2]))
-             operands[2] = force_reg (<VEL>mode, operands[2]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                                           v, operands[2], operands[5],
-                                           <VM>mode);
-           emit_insn (gen_pred_msbc<mode> (operands[0], operands[1], v, operands[3],
-                                           operands[4], operands[5]));
-           DONE;
-         }
-      }
-    else
-      {
-       if (!rtx_equal_p (operands[2], const0_rtx))
-         operands[2] = force_reg (<VEL>mode, operands[2]);
-      }
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[2],
+       /* vl */operands[4],
+       <MODE>mode,
+       <VM>mode,
+       false,
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_msbc<mode> (operands[0], operands[1],
+              boardcast_scalar, operands[3], operands[4], operands[5]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_msbc<mode>_scalar"
   [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
        (unspec:<VM>
           [(plus:VI_QHS
             (vec_duplicate:VI_QHS
-              (match_operand:<VEL> 2 "register_operand" "   r"))
+              (match_operand:<VEL> 2 "reg_or_0_operand" "  rJ"))
             (match_operand:VI_QHS 1 "register_operand"  "  vr"))
            (unspec:<VM>
              [(match_operand 3 "vector_length_operand"  "  rK")
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
   "TARGET_VECTOR"
-  "vmadc.vx\t%0,%1,%2"
+  "vmadc.vx\t%0,%1,%z2"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
    (set_attr "vl_op_idx" "3")
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::simm5_p (operands[2]))
-      operands[2] = force_reg (<VEL>mode, operands[2]);
-    else if (!TARGET_64BIT)
-      {
-        rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[2], Pmode))
-         operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[2]));
-       else
-         {
-           if (CONST_INT_P (operands[2]))
-             operands[2] = force_reg (<VEL>mode, operands[2]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                                           v, operands[2], operands[3],
-                                           <VM>mode);
-           emit_insn (gen_pred_madc<mode>_overflow (operands[0], operands[1],
-                                                    v, operands[3], operands[4]));
-           DONE;
-         }
-      }
-    else
-      operands[2] = force_reg (<VEL>mode, operands[2]);
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[2],
+       /* vl */operands[3],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::simm5_p (operands[2]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_madc<mode>_overflow (operands[0], operands[1],
+              boardcast_scalar, operands[3], operands[4]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_madc<mode>_overflow_scalar"
   [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
        (unspec:<VM>
           [(plus:VI_D
             (vec_duplicate:VI_D
-              (match_operand:<VEL> 2 "register_operand" "   r"))
+              (match_operand:<VEL> 2 "reg_or_0_operand" "  rJ"))
             (match_operand:VI_D 1 "register_operand"    "  vr"))
            (unspec:<VM>
              [(match_operand 3 "vector_length_operand"  "  rK")
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
   "TARGET_VECTOR"
-  "vmadc.vx\t%0,%1,%2"
+  "vmadc.vx\t%0,%1,%z2"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
    (set_attr "vl_op_idx" "3")
           [(plus:VI_D
             (vec_duplicate:VI_D
               (sign_extend:<VEL>
-                (match_operand:<VSUBEL> 2 "register_operand" "   r")))
+                (match_operand:<VSUBEL> 2 "reg_or_0_operand" "  rJ")))
             (match_operand:VI_D 1 "register_operand"         "  vr"))
            (unspec:<VM>
              [(match_operand 3 "vector_length_operand"       "  rK")
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
   "TARGET_VECTOR"
-  "vmadc.vx\t%0,%1,%2"
+  "vmadc.vx\t%0,%1,%z2"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
    (set_attr "vl_op_idx" "3")
               (reg:SI VL_REGNUM)
               (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
   "TARGET_VECTOR"
-  {
-    if (!TARGET_64BIT)
-      {
-        rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[2], Pmode))
-         {
-           if (!rtx_equal_p (operands[2], const0_rtx))
-             operands[2] = force_reg (Pmode, operands[2]);
-           operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[2]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[2]))
-             operands[2] = force_reg (<VEL>mode, operands[2]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                                           v, operands[2], operands[3],
-                                           <VM>mode);
-           emit_insn (gen_pred_msbc<mode>_overflow (operands[0], operands[1],
-                                                    v, operands[3], operands[4]));
-           DONE;
-         }
-      }
-    else
-      {
-       if (!rtx_equal_p (operands[2], const0_rtx))
-         operands[2] = force_reg (<VEL>mode, operands[2]);
-      }
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[2],
+       /* vl */operands[3],
+       <MODE>mode,
+       <VM>mode,
+       false,
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_msbc<mode>_overflow (operands[0], operands[1],
+              boardcast_scalar, operands[3], operands[4]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_msbc<mode>_overflow_scalar"
   [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
            (match_operand:VI_D 3 "register_operand"))
          (match_operand:VI_D 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::has_vi_variant_p (<CODE>, operands[4]))
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[4], Pmode))
-         operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[4]));
-       else
-         {
-           if (CONST_INT_P (operands[4]))
-             operands[4] = force_reg (<VEL>mode, operands[4]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[4], operands[5], <VM>mode);
-           emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
-                       operands[2], operands[3], v, operands[5],
-                       operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[4],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::has_vi_variant_p (<CODE>, operands[4]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
+              operands[2], operands[3], boardcast_scalar, operands[5],
+              operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_<optab><mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
              (match_operand:<VEL> 4 "reg_or_int_operand")))
          (match_operand:VI_D 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (riscv_vector::has_vi_variant_p (<CODE>, operands[4]))
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[4], Pmode))
-         operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[4]));
-       else
-         {
-           if (CONST_INT_P (operands[4]))
-             operands[4] = force_reg (<VEL>mode, operands[4]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[4], operands[5], <VM>mode);
-           emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
-                       operands[2], operands[3], v, operands[5],
-                       operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      operands[4] = force_reg (<VEL>mode, operands[4]);
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[4],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::has_vi_variant_p (<CODE>, operands[4]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_<optab><mode> (operands[0], operands[1],
+              operands[2], operands[3], boardcast_scalar, operands[5],
+              operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_<optab><mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
             (match_operand:<VEL> 4 "reg_or_int_operand")] VSAT_ARITH_OP)
          (match_operand:VI_D 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[4], Pmode))
-         {
-           if (!rtx_equal_p (operands[4], const0_rtx))
-             operands[4] = force_reg (Pmode, operands[4]);
-           operands[4] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[4]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[4]))
-             operands[4] = force_reg (<VEL>mode, operands[4]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[4], operands[5], <VM>mode);
-           emit_insn (gen_pred_<sat_op><mode> (operands[0], operands[1],
-                       operands[2], operands[3], v, operands[5],
-                       operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      {
-       if (!rtx_equal_p (operands[4], const0_rtx))
-         operands[4] = force_reg (<VEL>mode, operands[4]);
-      }
-  })
+{
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[4],
+       /* vl */operands[5],
+       <MODE>mode,
+       <VM>mode,
+       false,
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_<sat_op><mode> (operands[0], operands[1],
+              operands[2], operands[3], boardcast_scalar, operands[5],
+              operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 (define_insn "*pred_<sat_op><mode>_scalar"
   [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr")
                (match_operand:<VEL> 5 "reg_or_int_operand"))])
          (match_operand:<VM> 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    enum rtx_code code = GET_CODE (operands[3]);
-
-    if (riscv_vector::has_vi_variant_p (code, operands[5]))
-      operands[5] = force_reg (<VEL>mode, operands[5]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[5], Pmode))
-         {
-           if (!rtx_equal_p (operands[5], const0_rtx))
-             operands[5] = force_reg (Pmode, operands[5]);
-           operands[5] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[5]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[5]))
-             operands[5] = force_reg (<VEL>mode, operands[5]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[5], operands[6], <VM>mode);
-           if (code == LT || code == LTU)
-               emit_insn (gen_pred_ltge<mode> (operands[0], operands[1],
-                          operands[2], operands[3], operands[4], v,
-                          operands[6], operands[7], operands[8]));
-           else
-               emit_insn (gen_pred_cmp<mode> (operands[0], operands[1],
-                          operands[2], operands[3], operands[4], v,
-                          operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      operands[5] = force_reg (<VEL>mode, operands[5]);
-  })
+{
+  enum rtx_code code = GET_CODE (operands[3]);
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[5],
+       /* vl */operands[6],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::has_vi_variant_p (code, operands[5]),
+       code == LT || code == LTU ?
+         [] (rtx *operands, rtx boardcast_scalar) {
+           emit_insn (gen_pred_ltge<mode> (operands[0], operands[1],
+               operands[2], operands[3], operands[4], boardcast_scalar,
+               operands[6], operands[7], operands[8]));
+          }
+       :
+         [] (rtx *operands, rtx boardcast_scalar) {
+           emit_insn (gen_pred_cmp<mode> (operands[0], operands[1],
+               operands[2], operands[3], operands[4], boardcast_scalar,
+               operands[6], operands[7], operands[8]));
+          }))
+    DONE;
+})
 
 (define_expand "@pred_eqne<mode>_scalar"
   [(set (match_operand:<VM> 0 "register_operand")
              (match_operand:VI_D 4 "register_operand")])
          (match_operand:<VM> 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
-  {
-    enum rtx_code code = GET_CODE (operands[3]);
-
-    if (riscv_vector::has_vi_variant_p (code, operands[5]))
-      operands[5] = force_reg (<VEL>mode, operands[5]);
-    else if (!TARGET_64BIT)
-      {
-       rtx v = gen_reg_rtx (<MODE>mode);
-
-       if (immediate_operand (operands[5], Pmode))
-         {
-           if (!rtx_equal_p (operands[5], const0_rtx))
-             operands[5] = force_reg (Pmode, operands[5]);
-           operands[5] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[5]);
-         }
-       else
-         {
-           if (CONST_INT_P (operands[5]))
-             operands[5] = force_reg (<VEL>mode, operands[5]);
-
-           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[5], operands[6], <VM>mode);
-           emit_insn (gen_pred_cmp<mode> (operands[0], operands[1],
-                      operands[2], operands[3], operands[4], v,
-                      operands[6], operands[7], operands[8]));
-           DONE;
-         }
-      }
-    else
-      operands[5] = force_reg (<VEL>mode, operands[5]);
-  })
+{
+  enum rtx_code code = GET_CODE (operands[3]);
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[5],
+       /* vl */operands[6],
+       <MODE>mode,
+       <VM>mode,
+       riscv_vector::has_vi_variant_p (code, operands[5]),
+       [] (rtx *operands, rtx boardcast_scalar) {
+         emit_insn (gen_pred_cmp<mode> (operands[0], operands[1],
+               operands[2], operands[3], operands[4], boardcast_scalar,
+               operands[6], operands[7], operands[8]));
+        }))
+    DONE;
+})
 
 ;; We don't use early-clobber for LMUL <= 1 to get better codegen.
 (define_insn "*pred_cmp<mode>_scalar"
          (match_operand:VI_D 5 "vector_merge_operand")))]
   "TARGET_VECTOR"
 {
-  if (!TARGET_64BIT)
-    {
-      rtx v = gen_reg_rtx (<MODE>mode);
-
-      if (immediate_operand (operands[2], Pmode))
-        operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode,
-               force_reg (Pmode, operands[2]));
-      else
-        {
-          if (CONST_INT_P (operands[2]))
-            operands[2] = force_reg (<VEL>mode, operands[2]);
-
-         riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
-                       v, operands[2], operands[6], <VM>mode);
+  if (riscv_vector::sew64_scalar_helper (
+       operands,
+       /* scalar op */&operands[2],
+       /* vl */operands[6],
+       <MODE>mode,
+       <VM>mode,
+       false,
+       [] (rtx *operands, rtx boardcast_scalar) {
          emit_insn (gen_pred_mul_<optab><mode> (operands[0], operands[1],
-                       v, operands[3], operands[4], operands[5], operands[6],
-                       operands[7], operands[8], operands[9]));
-         DONE;
-       }
-    }
-   else
-    operands[2] = force_reg (<VEL>mode, operands[2]);
+              boardcast_scalar, operands[3], operands[4], operands[5],
+              operands[6], operands[7], operands[8], operands[9]));
+        }))
+    DONE;
 })
 
 (define_insn "*pred_mul_<optab><mode>_undef_merge_extended_scalar"