;; cmtst
+(define_insn "aarch64_cmtst<mode><vczle><vczbe>"
+ [(set (match_operand:<V_INT_EQUIV> 0 "register_operand" "=w")
+ (neg:<V_INT_EQUIV>
+ (ne:<V_INT_EQUIV>
+ (and:VDQ_I
+ (match_operand:VDQ_I 1 "register_operand" "w")
+ (match_operand:VDQ_I 2 "register_operand" "w"))
+ (match_operand:VDQ_I 3 "aarch64_simd_imm_zero"))))
+ ]
+ "TARGET_SIMD"
+ "cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
+ [(set_attr "type" "neon_tst<q>")]
+)
;; Although neg (ne (and x y) 0) is the natural way of expressing a cmtst,
-;; we don't have any insns using ne, and aarch64_vcond outputs
-;; not (neg (eq (and x y) 0))
-;; which is rewritten by simplify_rtx as
-;; plus (eq (and x y) 0) -1.
+;; earlier versions of GCC simplified this as plus (eq (and x y) 0) -1.
-(define_insn "aarch64_cmtst<mode><vczle><vczbe>"
+(define_insn "*aarch64_cmtst<mode><vczle><vczbe>"
[(set (match_operand:<V_INT_EQUIV> 0 "register_operand" "=w")
(plus:<V_INT_EQUIV>
(eq:<V_INT_EQUIV>
[(set_attr "type" "neon_tst<q>")]
)
+;; One can also get a cmtsts by having to combine a
+;; neg (ne x 0) in which case you rewrite it to
+;; a comparison against itself
+
+(define_insn "*aarch64_cmtst_same_<mode><vczle><vczbe>"
+ [(set (match_operand:<V_INT_EQUIV> 0 "register_operand" "=w")
+ (neg:<V_INT_EQUIV>
+ (ne:<V_INT_EQUIV>
+ (match_operand:VDQ_I 1 "register_operand" "w")
+ (match_operand:VDQ_I 2 "aarch64_simd_imm_zero"))))
+ ]
+ "TARGET_SIMD"
+ "cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>1<Vmtype>"
+ [(set_attr "type" "neon_tst<q>")]
+)
+
;; One can also get a cmtsts by having to combine a
;; not (neq (eq x 0)) in which case you rewrite it to
;; a comparison against itself