@@ -770,6 +770,45 @@
}
)
+;; For 64-bit modes we use ushl/r, as this does not require a SIMD zero.
+(define_insn "vec_shr_<mode>"
+ [(set (match_operand:VD 0 "register_operand" "=w")
+ (lshiftrt:VD (match_operand:VD 1 "register_operand" "w")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "TARGET_SIMD"
+ "ushr %d0, %d1, %2"
+ [(set_attr "type" "neon_shift_imm")]
+)
+
+(define_expand "vec_shr_<mode>"
+ [(set (match_operand:VQ 0 "register_operand" "=w")
+ (lshiftrt:VQ (match_operand:VQ 1 "register_operand" "w")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "TARGET_SIMD"
+{
+ HOST_WIDE_INT num_bits = INTVAL (operands[2]);
+ HOST_WIDE_INT elem_bits = GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
+ rtx zero_reg = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));
+
+ gcc_assert (GET_MODE_BITSIZE (<MODE>mode) == 128);
+ gcc_assert (num_bits % elem_bits == 0);
+
+ if (num_bits == 0)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+ }
+ else if (num_bits == 128)
+ {
+ emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
+ DONE;
+ }
+
+ emit_insn (gen_aarch64_ext<mode> (operands[0], operands[1], zero_reg,
+ GEN_INT (num_bits / elem_bits)));
+ DONE;
+})
+
(define_insn "aarch64_simd_vec_setv2di"
[(set (match_operand:V2DI 0 "register_operand" "=w,w")
(vec_merge:V2DI
@@ -3323,6 +3323,7 @@ proc check_effective_target_vect_shift { } {
proc check_effective_target_whole_vector_shift { } {
if { [istarget x86_64-*-*]
|| [istarget ia64-*-*]
+ || [istarget aarch64*-*-*]
|| ([check_effective_target_arm32]
&& [check_effective_target_arm_little_endian])
|| ([istarget mips*-*-*]