@@ -5631,14 +5631,29 @@
; the semantics of the instructions require.
(define_insn "vec_pack_trunc_<mode>"
- [(set (match_operand:<V_narrow_pack> 0 "register_operand" "=&w")
+ [(set (match_operand:<V_narrow_pack> 0 "register_operand" "=w")
(vec_concat:<V_narrow_pack>
(truncate:<V_narrow>
(match_operand:VN 1 "register_operand" "w"))
(truncate:<V_narrow>
(match_operand:VN 2 "register_operand" "w"))))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
- "vmovn.i<V_sz_elem>\t%e0, %q1\;vmovn.i<V_sz_elem>\t%f0, %q2"
+ {
+ /* If operand1 and operand2 are identical, then the second
+ narrowing operation isn't needed as the values obtained
+ in both parts of the destination q register are identical.
+ This precludes the need for an early clobber in the destination
+ operand. */
+ if (rtx_equal_p (operands[1], operands[2]))
+ return "vmovn.i<V_sz_elem>\\t%e0, %q1\;vmov.i<V_sz_elem>\\t%f0, %e0";
+ else
+ {
+ if (reg_overlap_mentioned_p (operands[0], operands[2]))
+ return "vmovn.i<V_sz_elem>\\t%f0, %q2\;vmovn.i<V_sz_elem>\\t%e0, %q1";
+ else
+ return "vmovn.i<V_sz_elem>\\t%e0, %q1\;vmovn.i<V_sz_elem>\\t%f0, %q2";
+ }
+ }
[(set_attr "neon_type" "neon_shift_1")
(set_attr "length" "8")]
)