gcc/
authorJulian Brown <julian@codesourcery.com>
Thu, 26 Jul 2007 13:59:57 +0000 (13:59 +0000)
committerJulian Brown <jules@gcc.gnu.org>
Thu, 26 Jul 2007 13:59:57 +0000 (13:59 +0000)
* config/arm/arm-protos.h (neon_lane_bounds, neon_const_bounds)
(neon_element_bits): Add prototypes.
* config/arm/arm.c (bounds_check, neon_lane_bounds)
(neon_const_bounds, neon_element_bits): New functions.
* config/arm/neon.md (neon_vget_lane<mode>, neon_vget_lanedi)
(neon_vget_lanev2di, neon_vset_lane<mode>, neon_vset_lanedi)
(neon_vset_lanev2di, neon_vdup_lane<mode>, neon_vdup_lanedi)
(neon_vdup_lanev2di, neon_vcvt_n<mode>, neon_vmul_lane<mode>)
(neon_vmull_lane<mode>, neon_vqdmull_lane<mode>)
(neon_vqdmulh_lane<mode>, neon_vmla_lane<mode>)
(neon_vmlal_lane<mode>, neon_vqdmlal_lane<mode>)
(neon_vmls_lane<mode>, neon_vmlsl_lane<mode>)
(neon_vqdmlsl_lane<mode>, neon_vext<mode>, neon_vshr_n<mode>)
(neon_vshrn_n<mode>, neon_vqshrn_n<mode>, neon_vqshrun_n<mode>)
(neon_vshl_n<mode>, neon_vshl_n<mode>, neon_vqshl_n<mode>)
(neon_vqshlu_n<mode>, neon_vshll_n<mode>, neon_vsra_n<mode>)
(neon_vsri_n<mode>, neon_vsli_n<mode>): Add bounds checks.

From-SVN: r126958

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/neon.md

index f789148..017187c 100644 (file)
@@ -1,3 +1,23 @@
+2007-07-26  Julian Brown  <julian@codesourcery.com>
+
+       * config/arm/arm-protos.h (neon_lane_bounds, neon_const_bounds)
+       (neon_element_bits): Add prototypes.
+       * config/arm/arm.c (bounds_check, neon_lane_bounds)
+       (neon_const_bounds, neon_element_bits): New functions.
+       * config/arm/neon.md (neon_vget_lane<mode>, neon_vget_lanedi)
+       (neon_vget_lanev2di, neon_vset_lane<mode>, neon_vset_lanedi)
+       (neon_vset_lanev2di, neon_vdup_lane<mode>, neon_vdup_lanedi)
+       (neon_vdup_lanev2di, neon_vcvt_n<mode>, neon_vmul_lane<mode>)
+       (neon_vmull_lane<mode>, neon_vqdmull_lane<mode>)
+       (neon_vqdmulh_lane<mode>, neon_vmla_lane<mode>)
+       (neon_vmlal_lane<mode>, neon_vqdmlal_lane<mode>)
+       (neon_vmls_lane<mode>, neon_vmlsl_lane<mode>)
+       (neon_vqdmlsl_lane<mode>, neon_vext<mode>, neon_vshr_n<mode>)
+       (neon_vshrn_n<mode>, neon_vqshrn_n<mode>, neon_vqshrun_n<mode>)
+       (neon_vshl_n<mode>, neon_vshl_n<mode>, neon_vqshl_n<mode>)
+       (neon_vqshlu_n<mode>, neon_vshll_n<mode>, neon_vsra_n<mode>)
+       (neon_vsri_n<mode>, neon_vsli_n<mode>): Add bounds checks.
+
 2007-07-26  Nathan Froyd  <froydnj@codesourcery.com>
 
        * config/vxworks.h (VXWORKS_LINK_SPEC): Fix typo.
index f238026..f7439f2 100644 (file)
@@ -76,6 +76,9 @@ extern char *neon_output_logic_immediate (const char *, rtx *,
 extern void neon_pairwise_reduce (rtx, rtx, enum machine_mode,
                                  rtx (*) (rtx, rtx, rtx));
 extern void neon_expand_vector_init (rtx, rtx);
+extern void neon_lane_bounds (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
+extern void neon_const_bounds (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
+extern HOST_WIDE_INT neon_element_bits (enum machine_mode);
 extern void neon_reinterpret (rtx, rtx);
 extern void neon_emit_pair_result_insn (enum machine_mode,
                                        rtx (*) (rtx, rtx, rtx, rtx),
index de0fb41..47f3394 100644 (file)
@@ -6234,6 +6234,49 @@ neon_expand_vector_init (rtx target, rtx vals)
   emit_move_insn (target, mem);
 }
 
+/* Ensure OPERAND lies between LOW (inclusive) and HIGH (exclusive).  Raise
+   ERR if it doesn't.  FIXME: NEON bounds checks occur late in compilation, so
+   reported source locations are bogus.  */
+
+static void
+bounds_check (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high,
+             const char *err)
+{
+  HOST_WIDE_INT lane;
+
+  gcc_assert (GET_CODE (operand) == CONST_INT);
+
+  lane = INTVAL (operand);
+
+  if (lane < low || lane >= high)
+    error (err);
+}
+
+/* Bounds-check lanes.  */
+
+void
+neon_lane_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high)
+{
+  bounds_check (operand, low, high, "lane out of range");
+}
+
+/* Bounds-check constants.  */
+
+void
+neon_const_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high)
+{
+  bounds_check (operand, low, high, "constant out of range");
+}
+
+HOST_WIDE_INT
+neon_element_bits (enum machine_mode mode)
+{
+  if (mode == DImode)
+    return GET_MODE_BITSIZE (mode);
+  else
+    return GET_MODE_BITSIZE (GET_MODE_INNER (mode));
+}
+
 \f
 /* Predicates for `match_operand' and `match_operator'.  */
 
index c62ffc3..06b9b3c 100644 (file)
                           (match_operand:SI 3 "immediate_operand" "i")]
                          UNSPEC_VGET_LANE))]
   "TARGET_NEON"
-  "vmov%?.%t3%#<V_sz_elem>\t%0, %P1[%c2]"
+{
+  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmov%?.%t3%#<V_sz_elem>\t%0, %P1[%c2]";
+}
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_bp_simple")]
 )
                    (match_operand:SI 3 "immediate_operand" "i")]
                   UNSPEC_VGET_LANE))]
   "TARGET_NEON"
-  "vmov%?\t%Q0, %R0, %P1  @ di"
+{
+  neon_lane_bounds (operands[2], 0, 1);
+  return "vmov%?\t%Q0, %R0, %P1  @ di";
+}
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_bp_simple")]
 )
   unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
   unsigned int elt = INTVAL (operands[2]);
 
+  neon_lane_bounds (operands[2], 0, halfelts * 2);
+
   ops[0] = operands[0];
   ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
   ops[2] = GEN_INT (elt % halfelts);
   unsigned int regno = REGNO (operands[1]);
   unsigned int elt = INTVAL (operands[2]);
 
+  neon_lane_bounds (operands[2], 0, 2);
+
   ops[0] = operands[0];
   ops[1] = gen_rtx_REG (DImode, regno + 2 * elt);
   output_asm_insn ("vmov%?\t%Q0, %R0, %P1  @ v2di", ops);
                     (match_operand:SI 3 "immediate_operand" "i")]
                    UNSPEC_VSET_LANE))]
   "TARGET_NEON"
-  "vmov%?.<V_sz_elem>\t%P0[%c3], %1"
+{
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmov%?.<V_sz_elem>\t%P0[%c3], %1";
+}
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_bp_simple")]
 )
                     (match_operand:SI 3 "immediate_operand" "i")]
                    UNSPEC_VSET_LANE))]
   "TARGET_NEON"
-  "vmov%?\t%P0, %Q1, %R1  @ di"
+{
+  neon_lane_bounds (operands[3], 0, 1);
+  return "vmov%?\t%P0, %Q1, %R1  @ di";
+}
   [(set_attr "predicable" "yes")
    (set_attr "neon_type" "neon_bp_simple")]
 )
   unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
   unsigned int elt = INTVAL (operands[3]);
 
+  neon_lane_bounds (operands[3], 0, halfelts * 2);
+
   ops[0] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
   ops[1] = operands[1];
   ops[2] = GEN_INT (elt % halfelts);
   unsigned int regno = REGNO (operands[0]);
   unsigned int elt = INTVAL (operands[3]);
 
+  neon_lane_bounds (operands[3], 0, 2);
+
   ops[0] = gen_rtx_REG (DImode, regno + 2 * elt);
   ops[1] = operands[1];
   output_asm_insn ("vmov%?\t%P0, %Q1, %R1  @ v2di", ops);
                    (match_operand:SI 2 "immediate_operand" "i")]
                    UNSPEC_VDUP_LANE))]
   "TARGET_NEON"
-  "vdup.<V_sz_elem>\t%P0, %P1[%c2]"
+{
+  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vdup.<V_sz_elem>\t%P0, %P1[%c2]";
+}
   ;; Assume this schedules like vmov.
   [(set_attr "neon_type" "neon_bp_simple")]
 )
                    (match_operand:SI 2 "immediate_operand" "i")]
                    UNSPEC_VDUP_LANE))]
   "TARGET_NEON"
-  "vdup.<V_sz_elem>\t%q0, %P1[%c2]"
+{
+  neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_HALF>mode));
+  return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
+}
   ;; Assume this schedules like vmov.
   [(set_attr "neon_type" "neon_bp_simple")]
 )
                    UNSPEC_VDUP_LANE))]
   "TARGET_NEON"
 {
+  neon_lane_bounds (operands[2], 0, 1);
   emit_move_insn (operands[0], operands[1]);
   DONE;
 })
                      (match_operand:SI 2 "immediate_operand" "i")]
                      UNSPEC_VDUP_LANE))]
   "TARGET_NEON"
-  "vmov\t%e0, %P1\;vmov\t%f0, %P1"
+{
+  neon_lane_bounds (operands[2], 0, 1);
+  return "vmov\t%e0, %P1\;vmov\t%f0, %P1";
+}
   [(set_attr "length" "8")
    (set_attr "neon_type" "neon_bp_simple")]
 )
                            (match_operand:SI 3 "immediate_operand" "i")]
                          UNSPEC_VCVT_N))]
   "TARGET_NEON"
-  "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2"
+{
+  neon_const_bounds (operands[2], 1, 33);
+  return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
                            (match_operand:SI 3 "immediate_operand" "i")]
                          UNSPEC_VCVT_N))]
   "TARGET_NEON"
-  "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2"
+{
+  neon_const_bounds (operands[2], 1, 33);
+  return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
                    (const_string "neon_fp_vadd_ddd_vabs_dd")
                      (match_operand:SI 4 "immediate_operand" "i")]
                     UNSPEC_VMUL_LANE))]
   "TARGET_NEON"
-  "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]"
+{
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
                    (const_string "neon_fp_vmul_ddd")
                      (match_operand:SI 4 "immediate_operand" "i")]
                     UNSPEC_VMUL_LANE))]
   "TARGET_NEON"
-  "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]"
+{
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
+  return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
                    (const_string "neon_fp_vmul_qqd")
                            (match_operand:SI 4 "immediate_operand" "i")]
                           UNSPEC_VMULL_LANE))]
   "TARGET_NEON"
-  "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]"
+{
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
                            (match_operand:SI 4 "immediate_operand" "i")]
                           UNSPEC_VQDMULL_LANE))]
   "TARGET_NEON"
-  "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]"
+{
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
                       (match_operand:SI 4 "immediate_operand" "i")]
                       UNSPEC_VQDMULH_LANE))]
   "TARGET_NEON"
-  "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]"
+{
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
                       (match_operand:SI 4 "immediate_operand" "i")]
                       UNSPEC_VQDMULH_LANE))]
   "TARGET_NEON"
-  "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]"
+{
+  neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
                      (match_operand:SI 5 "immediate_operand" "i")]
                      UNSPEC_VMLA_LANE))]
   "TARGET_NEON"
-  "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
                    (const_string "neon_fp_vmla_ddd_scalar")
                      (match_operand:SI 5 "immediate_operand" "i")]
                      UNSPEC_VMLA_LANE))]
   "TARGET_NEON"
-  "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
                    (const_string "neon_fp_vmla_qqq_scalar")
                            (match_operand:SI 5 "immediate_operand" "i")]
                           UNSPEC_VMLAL_LANE))]
   "TARGET_NEON"
-  "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
                            (match_operand:SI 5 "immediate_operand" "i")]
                           UNSPEC_VQDMLAL_LANE))]
   "TARGET_NEON"
-  "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
                      (match_operand:SI 5 "immediate_operand" "i")]
                     UNSPEC_VMLS_LANE))]
   "TARGET_NEON"
-  "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
                    (const_string "neon_fp_vmla_ddd_scalar")
                      (match_operand:SI 5 "immediate_operand" "i")]
                     UNSPEC_VMLS_LANE))]
   "TARGET_NEON"
-  "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
                    (const_string "neon_fp_vmla_qqq_scalar")
                            (match_operand:SI 5 "immediate_operand" "i")]
                           UNSPEC_VMLSL_LANE))]
   "TARGET_NEON"
-  "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
                            (match_operand:SI 5 "immediate_operand" "i")]
                           UNSPEC_VQDMLSL_LANE))]
   "TARGET_NEON"
-  "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]"
+{
+  neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
+}
   [(set (attr "neon_type")
      (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
                    (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
                       (match_operand:SI 3 "immediate_operand" "i")]
                      UNSPEC_VEXT))]
   "TARGET_NEON"
-  "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3"
+{
+  neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
+  return "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3";
+}
   [(set (attr "neon_type")
       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
                     (const_string "neon_bp_simple")
                        (match_operand:SI 3 "immediate_operand" "i")]
                       UNSPEC_VSHR_N))]
   "TARGET_NEON"
-  "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"
+{
+  neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) + 1);
+  return "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
+}
   [(set_attr "neon_type" "neon_shift_1")]
 )
 
                            (match_operand:SI 3 "immediate_operand" "i")]
                            UNSPEC_VSHRN_N))]
   "TARGET_NEON"
-  "v%O3shrn.<V_if_elem>\t%P0, %q1, %2"
+{
+  neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
+  return "v%O3shrn.<V_if_elem>\t%P0, %q1, %2";
+}
   [(set_attr "neon_type" "neon_shift_1")]
 )
 
                            (match_operand:SI 3 "immediate_operand" "i")]
                            UNSPEC_VQSHRN_N))]
   "TARGET_NEON"
-  "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2"
+{
+  neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
+  return "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2";
+}
   [(set_attr "neon_type" "neon_shift_2")]
 )
 
                            (match_operand:SI 3 "immediate_operand" "i")]
                            UNSPEC_VQSHRUN_N))]
   "TARGET_NEON"
-  "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2"
+{
+  neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
+  return "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2";
+}
   [(set_attr "neon_type" "neon_shift_2")]
 )
 
                        (match_operand:SI 3 "immediate_operand" "i")]
                       UNSPEC_VSHL_N))]
   "TARGET_NEON"
-  "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2"
+{
+  neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
+  return "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2";
+}
   [(set_attr "neon_type" "neon_shift_1")]
 )
 
                        (match_operand:SI 3 "immediate_operand" "i")]
                       UNSPEC_VQSHL_N))]
   "TARGET_NEON"
-  "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"
+{
+  neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
+  return "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
+}
   [(set_attr "neon_type" "neon_shift_2")]
 )
 
                        (match_operand:SI 3 "immediate_operand" "i")]
                       UNSPEC_VQSHLU_N))]
   "TARGET_NEON"
-  "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"
+{
+  neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
+  return "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
+}
   [(set_attr "neon_type" "neon_shift_2")]
 )
 
                           (match_operand:SI 3 "immediate_operand" "i")]
                          UNSPEC_VSHLL_N))]
   "TARGET_NEON"
-  "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2"
+{
+  neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
+  return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2";
+}
   [(set_attr "neon_type" "neon_shift_1")]
 )
 
                        (match_operand:SI 4 "immediate_operand" "i")]
                       UNSPEC_VSRA_N))]
   "TARGET_NEON"
-  "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"
+{
+  neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
+  return "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
+}
   [(set_attr "neon_type" "neon_vsra_vrsra")]
 )
 
                        (match_operand:SI 3 "immediate_operand" "i")]
                       UNSPEC_VSRI))]
   "TARGET_NEON"
-  "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"
+{
+  neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
+  return "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
+}
   [(set (attr "neon_type")
       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
                     (const_string "neon_shift_1")
                        (match_operand:SI 3 "immediate_operand" "i")]
                       UNSPEC_VSLI))]
   "TARGET_NEON"
-  "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"
+{
+  neon_const_bounds (operands[3], 0, neon_element_bits (<MODE>mode));
+  return "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
+}
   [(set (attr "neon_type")
       (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
                     (const_string "neon_shift_1")