aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/gcc/config/aarch64/aarch64-simd.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/gcc/config/aarch64/aarch64-simd.md')
-rw-r--r--gcc-4.8/gcc/config/aarch64/aarch64-simd.md185
1 files changed, 159 insertions, 26 deletions
diff --git a/gcc-4.8/gcc/config/aarch64/aarch64-simd.md b/gcc-4.8/gcc/config/aarch64/aarch64-simd.md
index 00f3c3121..481222cf5 100644
--- a/gcc-4.8/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc-4.8/gcc/config/aarch64/aarch64-simd.md
@@ -21,7 +21,7 @@
; Main data types used by the insntructions
-(define_attr "simd_mode" "unknown,none,V8QI,V16QI,V4HI,V8HI,V2SI,V4SI,V2DI,V2SF,V4SF,V2DF,OI,CI,XI,DI,DF,SI,HI,QI"
+(define_attr "simd_mode" "unknown,none,V8QI,V16QI,V4HI,V8HI,V2SI,V4SI,V2DI,V2SF,V4SF,V2DF,OI,CI,XI,DI,DF,SI,SF,HI,QI"
(const_string "unknown"))
@@ -1548,12 +1548,12 @@
case LTU:
case GEU:
- emit_insn (gen_aarch64_cmhs<mode> (mask, operands[4], operands[5]));
+ emit_insn (gen_aarch64_cmgeu<mode> (mask, operands[4], operands[5]));
break;
case LEU:
case GTU:
- emit_insn (gen_aarch64_cmhi<mode> (mask, operands[4], operands[5]));
+ emit_insn (gen_aarch64_cmgtu<mode> (mask, operands[4], operands[5]));
break;
case NE:
@@ -3034,48 +3034,181 @@
)
-;; cm(eq|ge|le|lt|gt)
+;; cm(eq|ge|gt|lt|le)
+;; Note, we have constraints for Dz and Z as different expanders
+;; have different ideas of what should be passed to this pattern.
-(define_insn "aarch64_cm<cmp><mode>"
+(define_insn "aarch64_cm<optab><mode>"
[(set (match_operand:<V_cmp_result> 0 "register_operand" "=w,w")
- (unspec:<V_cmp_result>
- [(match_operand:VSDQ_I_DI 1 "register_operand" "w,w")
- (match_operand:VSDQ_I_DI 2 "aarch64_simd_reg_or_zero" "w,Z")]
- VCMP_S))]
+ (neg:<V_cmp_result>
+ (COMPARISONS:<V_cmp_result>
+ (match_operand:VDQ 1 "register_operand" "w,w")
+ (match_operand:VDQ 2 "aarch64_simd_reg_or_zero" "w,ZDz")
+ )))]
"TARGET_SIMD"
"@
- cm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>
- cm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, #0"
+ cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
+ cm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, #0"
[(set_attr "simd_type" "simd_cmp")
(set_attr "simd_mode" "<MODE>")]
)
-;; cm(hs|hi|tst)
+(define_insn_and_split "aarch64_cm<optab>di"
+ [(set (match_operand:DI 0 "register_operand" "=w,w,r")
+ (neg:DI
+ (COMPARISONS:DI
+ (match_operand:DI 1 "register_operand" "w,w,r")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz,r")
+ )))]
+ "TARGET_SIMD"
+ "@
+ cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
+ cm<optab>\t%d0, %d1, #0
+ #"
+ "reload_completed
+ /* We need to prevent the split from
+ happening in the 'w' constraint cases. */
+ && GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1]))"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (neg:DI
+ (COMPARISONS:DI
+ (match_operand 3 "cc_register" "")
+ (const_int 0))))]
+ {
+ enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
+ rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+ rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "DI")]
+)
+
+;; cm(hs|hi)
-(define_insn "aarch64_cm<cmp><mode>"
+(define_insn "aarch64_cm<optab><mode>"
[(set (match_operand:<V_cmp_result> 0 "register_operand" "=w")
- (unspec:<V_cmp_result>
- [(match_operand:VSDQ_I_DI 1 "register_operand" "w")
- (match_operand:VSDQ_I_DI 2 "register_operand" "w")]
- VCMP_U))]
+ (neg:<V_cmp_result>
+ (UCOMPARISONS:<V_cmp_result>
+ (match_operand:VDQ 1 "register_operand" "w")
+ (match_operand:VDQ 2 "register_operand" "w")
+ )))]
"TARGET_SIMD"
- "cm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
+ "cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>"
[(set_attr "simd_type" "simd_cmp")
(set_attr "simd_mode" "<MODE>")]
)
-;; fcm(eq|ge|le|lt|gt)
+(define_insn_and_split "aarch64_cm<optab>di"
+ [(set (match_operand:DI 0 "register_operand" "=w,r")
+ (neg:DI
+ (UCOMPARISONS:DI
+ (match_operand:DI 1 "register_operand" "w,r")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,r")
+ )))]
+ "TARGET_SIMD"
+ "@
+ cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
+ #"
+ "reload_completed
+ /* We need to prevent the split from
+ happening in the 'w' constraint cases. */
+ && GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1]))"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (neg:DI
+ (UCOMPARISONS:DI
+ (match_operand 3 "cc_register" "")
+ (const_int 0))))]
+ {
+ enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
+ rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+ rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "DI")]
+)
+
+;; cmtst
+
+(define_insn "aarch64_cmtst<mode>"
+ [(set (match_operand:<V_cmp_result> 0 "register_operand" "=w")
+ (neg:<V_cmp_result>
+ (ne:<V_cmp_result>
+ (and:VDQ
+ (match_operand:VDQ 1 "register_operand" "w")
+ (match_operand:VDQ 2 "register_operand" "w"))
+ (vec_duplicate:<V_cmp_result> (const_int 0)))))]
+ "TARGET_SIMD"
+ "cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "<MODE>")]
+)
+
+(define_insn_and_split "aarch64_cmtstdi"
+ [(set (match_operand:DI 0 "register_operand" "=w,r")
+ (neg:DI
+ (ne:DI
+ (and:DI
+ (match_operand:DI 1 "register_operand" "w,r")
+ (match_operand:DI 2 "register_operand" "w,r"))
+ (const_int 0))))]
+ "TARGET_SIMD"
+ "@
+ cmtst\t%d0, %d1, %d2
+ #"
+ "reload_completed
+ /* We need to prevent the split from
+ happening in the 'w' constraint cases. */
+ && GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1]))"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (and:DI (match_dup 1)
+ (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0)
+ (neg:DI
+ (ne:DI
+ (match_operand 3 "cc_register" "")
+ (const_int 0))))]
+ {
+ rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]);
+ enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx);
+ rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx);
+ rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "DI")]
+)
+
+;; fcm(eq|ge|gt|le|lt)
-(define_insn "aarch64_cm<cmp><mode>"
+(define_insn "aarch64_cm<optab><mode>"
[(set (match_operand:<V_cmp_result> 0 "register_operand" "=w,w")
- (unspec:<V_cmp_result>
- [(match_operand:VDQF 1 "register_operand" "w,w")
- (match_operand:VDQF 2 "aarch64_simd_reg_or_zero" "w,Dz")]
- VCMP_S))]
+ (neg:<V_cmp_result>
+ (COMPARISONS:<V_cmp_result>
+ (match_operand:VALLF 1 "register_operand" "w,w")
+ (match_operand:VALLF 2 "aarch64_simd_reg_or_zero" "w,YDz")
+ )))]
"TARGET_SIMD"
"@
- fcm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>
- fcm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, 0"
+ fcm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
+ fcm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, 0"
[(set_attr "simd_type" "simd_fcmp")
(set_attr "simd_mode" "<MODE>")]
)