mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 15:31:11 +08:00
neon.md (UNSPEC_VCLE, [...]): New constants for unspecs.
gcc/ * config/arm/neon.md (UNSPEC_VCLE, UNSPEC_VCLT): New constants for unspecs. (vcond<mode>, vcondu<mode>): New expanders. (neon_vceq<mode>, neon_vcge<mode>, neon_vcgt<mode>): Support comparisons with zero. (neon_vcle<mode>, neon_vclt<mode>): New patterns. * config/arm/constraints.md (Dz): New constraint. From-SVN: r163780
This commit is contained in:
parent
07b8f0a812
commit
5bfc5baa90
@ -1,3 +1,13 @@
|
||||
2010-09-02 Julian Brown <julian@codesourcery.com>
|
||||
|
||||
* config/arm/neon.md (UNSPEC_VCLE, UNSPEC_VCLT): New constants for
|
||||
unspecs.
|
||||
(vcond<mode>, vcondu<mode>): New expanders.
|
||||
(neon_vceq<mode>, neon_vcge<mode>, neon_vcgt<mode>): Support
|
||||
comparisons with zero.
|
||||
(neon_vcle<mode>, neon_vclt<mode>): New patterns.
|
||||
* config/arm/constraints.md (Dz): New constraint.
|
||||
|
||||
2010-09-02 Anatoly Sokolov <aesok@post.ru>
|
||||
|
||||
* target.def (class_likely_spilled_p): New hook.
|
||||
|
@ -29,7 +29,7 @@
|
||||
;; in Thumb-1 state: I, J, K, L, M, N, O
|
||||
|
||||
;; The following multi-letter normal constraints have been used:
|
||||
;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di
|
||||
;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dz
|
||||
;; in Thumb-1 state: Pa, Pb, Pc, Pd
|
||||
;; in Thumb-2 state: Ps, Pt, Pu, Pv, Pw, Px
|
||||
|
||||
@ -199,6 +199,12 @@
|
||||
(and (match_code "const_double")
|
||||
(match_test "TARGET_32BIT && neg_const_double_rtx_ok_for_fpa (op)")))
|
||||
|
||||
(define_constraint "Dz"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a vector of constant zeros."
|
||||
(and (match_code "const_vector")
|
||||
(match_test "TARGET_NEON && op == CONST0_RTX (mode)")))
|
||||
|
||||
(define_constraint "Da"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a const_int, const_double or const_vector that can
|
||||
|
@ -140,7 +140,9 @@
|
||||
(UNSPEC_VUZP1 201)
|
||||
(UNSPEC_VUZP2 202)
|
||||
(UNSPEC_VZIP1 203)
|
||||
(UNSPEC_VZIP2 204)])
|
||||
(UNSPEC_VZIP2 204)
|
||||
(UNSPEC_VCLE 206)
|
||||
(UNSPEC_VCLT 207)])
|
||||
|
||||
|
||||
;; Attribute used to permit string comparisons against <VQH_mnem> in
|
||||
@ -1452,6 +1454,169 @@
|
||||
[(set_attr "neon_type" "neon_int_5")]
|
||||
)
|
||||
|
||||
;; Conditional instructions. These are comparisons with conditional moves for
|
||||
;; vectors. They perform the assignment:
|
||||
;;
|
||||
;; Vop0 = (Vop4 <op3> Vop5) ? Vop1 : Vop2;
|
||||
;;
|
||||
;; where op3 is <, <=, ==, !=, >= or >. Operations are performed
|
||||
;; element-wise.
|
||||
|
||||
(define_expand "vcond<mode>"
|
||||
[(set (match_operand:VDQW 0 "s_register_operand" "")
|
||||
(if_then_else:VDQW
|
||||
(match_operator 3 "arm_comparison_operator"
|
||||
[(match_operand:VDQW 4 "s_register_operand" "")
|
||||
(match_operand:VDQW 5 "nonmemory_operand" "")])
|
||||
(match_operand:VDQW 1 "s_register_operand" "")
|
||||
(match_operand:VDQW 2 "s_register_operand" "")))]
|
||||
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
|
||||
{
|
||||
rtx mask;
|
||||
int inverse = 0, immediate_zero = 0;
|
||||
/* See the description of "magic" bits in the 'T' case of
|
||||
arm_print_operand. */
|
||||
HOST_WIDE_INT magic_word = (<MODE>mode == V2SFmode || <MODE>mode == V4SFmode)
|
||||
? 3 : 1;
|
||||
rtx magic_rtx = GEN_INT (magic_word);
|
||||
|
||||
mask = gen_reg_rtx (<V_cmp_result>mode);
|
||||
|
||||
if (operands[5] == CONST0_RTX (<MODE>mode))
|
||||
immediate_zero = 1;
|
||||
else if (!REG_P (operands[5]))
|
||||
operands[5] = force_reg (<MODE>mode, operands[5]);
|
||||
|
||||
switch (GET_CODE (operands[3]))
|
||||
{
|
||||
case GE:
|
||||
emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
|
||||
magic_rtx));
|
||||
break;
|
||||
|
||||
case GT:
|
||||
emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
|
||||
magic_rtx));
|
||||
break;
|
||||
|
||||
case EQ:
|
||||
emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
|
||||
magic_rtx));
|
||||
break;
|
||||
|
||||
case LE:
|
||||
if (immediate_zero)
|
||||
emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
|
||||
magic_rtx));
|
||||
else
|
||||
emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
|
||||
magic_rtx));
|
||||
break;
|
||||
|
||||
case LT:
|
||||
if (immediate_zero)
|
||||
emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
|
||||
magic_rtx));
|
||||
else
|
||||
emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
|
||||
magic_rtx));
|
||||
break;
|
||||
|
||||
case NE:
|
||||
emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
|
||||
magic_rtx));
|
||||
inverse = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (inverse)
|
||||
emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
|
||||
operands[1]));
|
||||
else
|
||||
emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
|
||||
operands[2]));
|
||||
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "vcondu<mode>"
|
||||
[(set (match_operand:VDQIW 0 "s_register_operand" "")
|
||||
(if_then_else:VDQIW
|
||||
(match_operator 3 "arm_comparison_operator"
|
||||
[(match_operand:VDQIW 4 "s_register_operand" "")
|
||||
(match_operand:VDQIW 5 "s_register_operand" "")])
|
||||
(match_operand:VDQIW 1 "s_register_operand" "")
|
||||
(match_operand:VDQIW 2 "s_register_operand" "")))]
|
||||
"TARGET_NEON"
|
||||
{
|
||||
rtx mask;
|
||||
int inverse = 0, immediate_zero = 0;
|
||||
|
||||
mask = gen_reg_rtx (<V_cmp_result>mode);
|
||||
|
||||
if (operands[5] == CONST0_RTX (<MODE>mode))
|
||||
immediate_zero = 1;
|
||||
else if (!REG_P (operands[5]))
|
||||
operands[5] = force_reg (<MODE>mode, operands[5]);
|
||||
|
||||
switch (GET_CODE (operands[3]))
|
||||
{
|
||||
case GEU:
|
||||
emit_insn (gen_neon_vcge<mode> (mask, operands[4], operands[5],
|
||||
const0_rtx));
|
||||
break;
|
||||
|
||||
case GTU:
|
||||
emit_insn (gen_neon_vcgt<mode> (mask, operands[4], operands[5],
|
||||
const0_rtx));
|
||||
break;
|
||||
|
||||
case EQ:
|
||||
emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
|
||||
const0_rtx));
|
||||
break;
|
||||
|
||||
case LEU:
|
||||
if (immediate_zero)
|
||||
emit_insn (gen_neon_vcle<mode> (mask, operands[4], operands[5],
|
||||
const0_rtx));
|
||||
else
|
||||
emit_insn (gen_neon_vcge<mode> (mask, operands[5], operands[4],
|
||||
const0_rtx));
|
||||
break;
|
||||
|
||||
case LTU:
|
||||
if (immediate_zero)
|
||||
emit_insn (gen_neon_vclt<mode> (mask, operands[4], operands[5],
|
||||
const0_rtx));
|
||||
else
|
||||
emit_insn (gen_neon_vcgt<mode> (mask, operands[5], operands[4],
|
||||
const0_rtx));
|
||||
break;
|
||||
|
||||
case NE:
|
||||
emit_insn (gen_neon_vceq<mode> (mask, operands[4], operands[5],
|
||||
const0_rtx));
|
||||
inverse = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (inverse)
|
||||
emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[2],
|
||||
operands[1]));
|
||||
else
|
||||
emit_insn (gen_neon_vbsl<mode> (operands[0], mask, operands[1],
|
||||
operands[2]));
|
||||
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Patterns for builtins.
|
||||
|
||||
; good for plain vadd, vaddq.
|
||||
@ -1863,13 +2028,16 @@
|
||||
)
|
||||
|
||||
(define_insn "neon_vceq<mode>"
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
|
||||
(match_operand:VDQW 2 "s_register_operand" "w")
|
||||
(match_operand:SI 3 "immediate_operand" "i")]
|
||||
UNSPEC_VCEQ))]
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
|
||||
(unspec:<V_cmp_result>
|
||||
[(match_operand:VDQW 1 "s_register_operand" "w,w")
|
||||
(match_operand:VDQW 2 "nonmemory_operand" "w,Dz")
|
||||
(match_operand:SI 3 "immediate_operand" "i,i")]
|
||||
UNSPEC_VCEQ))]
|
||||
"TARGET_NEON"
|
||||
"vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
|
||||
"@
|
||||
vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
|
||||
vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, #0"
|
||||
[(set (attr "neon_type")
|
||||
(if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
|
||||
(if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
|
||||
@ -1879,13 +2047,16 @@
|
||||
)
|
||||
|
||||
(define_insn "neon_vcge<mode>"
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
|
||||
(match_operand:VDQW 2 "s_register_operand" "w")
|
||||
(match_operand:SI 3 "immediate_operand" "i")]
|
||||
UNSPEC_VCGE))]
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
|
||||
(unspec:<V_cmp_result>
|
||||
[(match_operand:VDQW 1 "s_register_operand" "w,w")
|
||||
(match_operand:VDQW 2 "nonmemory_operand" "w,Dz")
|
||||
(match_operand:SI 3 "immediate_operand" "i,i")]
|
||||
UNSPEC_VCGE))]
|
||||
"TARGET_NEON"
|
||||
"vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
|
||||
"@
|
||||
vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
|
||||
vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
|
||||
[(set (attr "neon_type")
|
||||
(if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
|
||||
(if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
|
||||
@ -1895,13 +2066,16 @@
|
||||
)
|
||||
|
||||
(define_insn "neon_vcgt<mode>"
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w")
|
||||
(match_operand:VDQW 2 "s_register_operand" "w")
|
||||
(match_operand:SI 3 "immediate_operand" "i")]
|
||||
UNSPEC_VCGT))]
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
|
||||
(unspec:<V_cmp_result>
|
||||
[(match_operand:VDQW 1 "s_register_operand" "w,w")
|
||||
(match_operand:VDQW 2 "nonmemory_operand" "w,Dz")
|
||||
(match_operand:SI 3 "immediate_operand" "i,i")]
|
||||
UNSPEC_VCGT))]
|
||||
"TARGET_NEON"
|
||||
"vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
|
||||
"@
|
||||
vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
|
||||
vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
|
||||
[(set (attr "neon_type")
|
||||
(if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
|
||||
(if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
|
||||
@ -1910,6 +2084,43 @@
|
||||
(const_string "neon_int_5")))]
|
||||
)
|
||||
|
||||
;; VCLE and VCLT only support comparisons with immediate zero (register
|
||||
;; variants are VCGE and VCGT with operands reversed).
|
||||
|
||||
(define_insn "neon_vcle<mode>"
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_cmp_result>
|
||||
[(match_operand:VDQW 1 "s_register_operand" "w")
|
||||
(match_operand:VDQW 2 "nonmemory_operand" "Dz")
|
||||
(match_operand:SI 3 "immediate_operand" "i")]
|
||||
UNSPEC_VCLE))]
|
||||
"TARGET_NEON"
|
||||
"vcle.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
|
||||
[(set (attr "neon_type")
|
||||
(if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
|
||||
(if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
|
||||
(const_string "neon_fp_vadd_ddd_vabs_dd")
|
||||
(const_string "neon_fp_vadd_qqq_vabs_qq"))
|
||||
(const_string "neon_int_5")))]
|
||||
)
|
||||
|
||||
(define_insn "neon_vclt<mode>"
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_cmp_result>
|
||||
[(match_operand:VDQW 1 "s_register_operand" "w")
|
||||
(match_operand:VDQW 2 "nonmemory_operand" "Dz")
|
||||
(match_operand:SI 3 "immediate_operand" "i")]
|
||||
UNSPEC_VCLT))]
|
||||
"TARGET_NEON"
|
||||
"vclt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
|
||||
[(set (attr "neon_type")
|
||||
(if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
|
||||
(if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
|
||||
(const_string "neon_fp_vadd_ddd_vabs_dd")
|
||||
(const_string "neon_fp_vadd_qqq_vabs_qq"))
|
||||
(const_string "neon_int_5")))]
|
||||
)
|
||||
|
||||
(define_insn "neon_vcage<mode>"
|
||||
[(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
|
||||
|
Loading…
x
Reference in New Issue
Block a user