altivec.md (UNSPEC_VCMPBFP, [...]): New constant defines.
* rs6000/altivec.md (UNSPEC_VCMPBFP, UNSPEC_VCMPEQUB, UNSPEC_VCMPEQUH, UNSPEC_VCMPEQUW, UNSPEC_VCMPGEFP, UNSPEC_VCMPGTUB, UNSPEC_VCMPGTSB, UNSPEC_VCMPGTUH, UNSPEC_VCMPGTSH, UNSPEC_VCMPGTUW, UNSPEC_VCMPGTSW, UNSPEC_VCMPGTFP, UNSPEC_VSEL4SI, UNSPEC_VSEL4SF, UNSPEC_VSEL8HI, UNSPEC_VSEL16QI, UNSPEC_VCOND_V4SI, UNSPEC_VCOND_V4SF, UNSPEC_VCOND_V8HI, UNSPEC_VCOND_V16QI, UNSPEC_VCONDU_V4SI, UNSPEC_VCONDU_V8HI, UNSPEC_VCONDU_V16QI): New constant defines. (vcondv4si, vcondv4sf, vcondv8hi, vcondv16qi, vconduv4si, vconduv8hi, vconduv16qi): New patterns. * rs6000/rs6000-protos.h (rs6000_emit_vector_cond_expr): New function. * rs6000/rs6000.c (rs6000_emit_vector_cond_expr): New function. (get_vec_cmp_insn): Same. (get_vsel_insn): Same. (rs6000_emit_vector_compare): Same. (rs6000_emit_vector_select): Same. (INSN_NOT_AVAILABLE): New. From-SVN: r88692
This commit is contained in:
parent
03d3f46d57
commit
21213b4c93
|
@ -1,3 +1,22 @@
|
|||
2004-10-07 Devang Patel <dpatel@apple.com>
|
||||
|
||||
* rs6000/altivec.md (UNSPEC_VCMPBFP, UNSPEC_VCMPEQUB, UNSPEC_VCMPEQUH,
|
||||
UNSPEC_VCMPEQUW, UNSPEC_VCMPGEFP, UNSPEC_VCMPGTUB, UNSPEC_VCMPGTSB,
|
||||
UNSPEC_VCMPGTUH, UNSPEC_VCMPGTSH, UNSPEC_VCMPGTUW, UNSPEC_VCMPGTSW,
|
||||
UNSPEC_VCMPGTFP, UNSPEC_VSEL4SI, UNSPEC_VSEL4SF, UNSPEC_VSEL8HI,
|
||||
UNSPEC_VSEL16QI, UNSPEC_VCOND_V4SI, UNSPEC_VCOND_V4SF, UNSPEC_VCOND_V8HI,
|
||||
UNSPEC_VCOND_V16QI, UNSPEC_VCONDU_V4SI, UNSPEC_VCONDU_V8HI,
|
||||
UNSPEC_VCONDU_V16QI): New constant defines.
|
||||
(vcondv4si, vcondv4sf, vcondv8hi, vcondv16qi, vconduv4si, vconduv8hi,
|
||||
vconduv16qi): New patterns.
|
||||
* rs6000/rs6000-protos.h (rs6000_emit_vector_cond_expr): New function.
|
||||
* rs6000/rs6000.c (rs6000_emit_vector_cond_expr): New function.
|
||||
(get_vec_cmp_insn): Same.
|
||||
(get_vsel_insn): Same.
|
||||
(rs6000_emit_vector_compare): Same.
|
||||
(rs6000_emit_vector_select): Same.
|
||||
(INSN_NOT_AVAILABLE): New.
|
||||
|
||||
2004-10-07 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
PR tree-optimization/17749
|
||||
|
|
|
@ -23,6 +23,30 @@
|
|||
[(UNSPEC_VSPLTISW 141)
|
||||
(UNSPEC_VSPLTISH 140)
|
||||
(UNSPEC_VSPLTISB 139)
|
||||
(UNSPEC_VCMPBFP 50)
|
||||
(UNSPEC_VCMPEQUB 51)
|
||||
(UNSPEC_VCMPEQUH 52)
|
||||
(UNSPEC_VCMPEQUW 53)
|
||||
(UNSPEC_VCMPEQFP 54)
|
||||
(UNSPEC_VCMPGEFP 55)
|
||||
(UNSPEC_VCMPGTUB 56)
|
||||
(UNSPEC_VCMPGTSB 57)
|
||||
(UNSPEC_VCMPGTUH 58)
|
||||
(UNSPEC_VCMPGTSH 59)
|
||||
(UNSPEC_VCMPGTUW 60)
|
||||
(UNSPEC_VCMPGTSW 61)
|
||||
(UNSPEC_VCMPGTFP 62)
|
||||
(UNSPEC_VSEL4SI 159)
|
||||
(UNSPEC_VSEL4SF 160)
|
||||
(UNSPEC_VSEL8HI 161)
|
||||
(UNSPEC_VSEL16QI 162)
|
||||
(UNSPEC_VCOND_V4SI 301)
|
||||
(UNSPEC_VCOND_V4SF 302)
|
||||
(UNSPEC_VCOND_V8HI 303)
|
||||
(UNSPEC_VCOND_V16QI 304)
|
||||
(UNSPEC_VCONDU_V4SI 305)
|
||||
(UNSPEC_VCONDU_V8HI 306)
|
||||
(UNSPEC_VCONDU_V16QI 307)
|
||||
])
|
||||
|
||||
;; Generic LVX load instruction.
|
||||
|
@ -496,7 +520,8 @@
|
|||
(define_insn "altivec_vcmpbfp"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
|
||||
(match_operand:V4SF 2 "register_operand" "v")] 50))]
|
||||
(match_operand:V4SF 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPBFP))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpbfp %0,%1,%2"
|
||||
[(set_attr "type" "veccmp")])
|
||||
|
@ -504,7 +529,8 @@
|
|||
(define_insn "altivec_vcmpequb"
|
||||
[(set (match_operand:V16QI 0 "register_operand" "=v")
|
||||
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
|
||||
(match_operand:V16QI 2 "register_operand" "v")] 51))]
|
||||
(match_operand:V16QI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPEQUB))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpequb %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -512,7 +538,8 @@
|
|||
(define_insn "altivec_vcmpequh"
|
||||
[(set (match_operand:V8HI 0 "register_operand" "=v")
|
||||
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
|
||||
(match_operand:V8HI 2 "register_operand" "v")] 52))]
|
||||
(match_operand:V8HI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPEQUH))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpequh %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -520,7 +547,8 @@
|
|||
(define_insn "altivec_vcmpequw"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V4SI 2 "register_operand" "v")] 53))]
|
||||
(match_operand:V4SI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPEQUW))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpequw %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -528,7 +556,8 @@
|
|||
(define_insn "altivec_vcmpeqfp"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
|
||||
(match_operand:V4SF 2 "register_operand" "v")] 54))]
|
||||
(match_operand:V4SF 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPEQFP))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpeqfp %0,%1,%2"
|
||||
[(set_attr "type" "veccmp")])
|
||||
|
@ -536,7 +565,8 @@
|
|||
(define_insn "altivec_vcmpgefp"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
|
||||
(match_operand:V4SF 2 "register_operand" "v")] 55))]
|
||||
(match_operand:V4SF 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGEFP))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgefp %0,%1,%2"
|
||||
[(set_attr "type" "veccmp")])
|
||||
|
@ -544,7 +574,8 @@
|
|||
(define_insn "altivec_vcmpgtub"
|
||||
[(set (match_operand:V16QI 0 "register_operand" "=v")
|
||||
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
|
||||
(match_operand:V16QI 2 "register_operand" "v")] 56))]
|
||||
(match_operand:V16QI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGTUB))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgtub %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -552,7 +583,8 @@
|
|||
(define_insn "altivec_vcmpgtsb"
|
||||
[(set (match_operand:V16QI 0 "register_operand" "=v")
|
||||
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
|
||||
(match_operand:V16QI 2 "register_operand" "v")] 57))]
|
||||
(match_operand:V16QI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGTSB))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgtsb %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -560,7 +592,8 @@
|
|||
(define_insn "altivec_vcmpgtuh"
|
||||
[(set (match_operand:V8HI 0 "register_operand" "=v")
|
||||
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
|
||||
(match_operand:V8HI 2 "register_operand" "v")] 58))]
|
||||
(match_operand:V8HI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGTUH))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgtuh %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -568,7 +601,8 @@
|
|||
(define_insn "altivec_vcmpgtsh"
|
||||
[(set (match_operand:V8HI 0 "register_operand" "=v")
|
||||
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
|
||||
(match_operand:V8HI 2 "register_operand" "v")] 59))]
|
||||
(match_operand:V8HI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGTSH))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgtsh %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -576,7 +610,8 @@
|
|||
(define_insn "altivec_vcmpgtuw"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V4SI 2 "register_operand" "v")] 60))]
|
||||
(match_operand:V4SI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGTUW))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgtuw %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -584,7 +619,8 @@
|
|||
(define_insn "altivec_vcmpgtsw"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V4SI 2 "register_operand" "v")] 61))]
|
||||
(match_operand:V4SI 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGTSW))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgtsw %0,%1,%2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
@ -592,7 +628,8 @@
|
|||
(define_insn "altivec_vcmpgtfp"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
|
||||
(match_operand:V4SF 2 "register_operand" "v")] 62))]
|
||||
(match_operand:V4SF 2 "register_operand" "v")]
|
||||
UNSPEC_VCMPGTFP))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vcmpgtfp %0,%1,%2"
|
||||
[(set_attr "type" "veccmp")])
|
||||
|
@ -1640,11 +1677,146 @@
|
|||
"vrefp %0,%1"
|
||||
[(set_attr "type" "vecfloat")])
|
||||
|
||||
(define_expand "vcondv4si"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V4SI 2 "register_operand" "v")
|
||||
(match_operand:V4SI 3 "comparison_operator" "")
|
||||
(match_operand:V4SI 4 "register_operand" "v")
|
||||
(match_operand:V4SI 5 "register_operand" "v")
|
||||
] UNSPEC_VCOND_V4SI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"
|
||||
{
|
||||
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
|
||||
operands[3], operands[4], operands[5]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
")
|
||||
|
||||
(define_expand "vconduv4si"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V4SI 2 "register_operand" "v")
|
||||
(match_operand:V4SI 3 "comparison_operator" "")
|
||||
(match_operand:V4SI 4 "register_operand" "v")
|
||||
(match_operand:V4SI 5 "register_operand" "v")
|
||||
] UNSPEC_VCONDU_V4SI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"
|
||||
{
|
||||
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
|
||||
operands[3], operands[4], operands[5]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
")
|
||||
|
||||
(define_expand "vcondv4sf"
|
||||
[(set (match_operand:V4SF 0 "register_operand" "=v")
|
||||
(unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V4SF 2 "register_operand" "v")
|
||||
(match_operand:V4SF 3 "comparison_operator" "")
|
||||
(match_operand:V4SF 4 "register_operand" "v")
|
||||
(match_operand:V4SF 5 "register_operand" "v")
|
||||
] UNSPEC_VCOND_V4SF))]
|
||||
"TARGET_ALTIVEC"
|
||||
"
|
||||
{
|
||||
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
|
||||
operands[3], operands[4], operands[5]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
")
|
||||
|
||||
(define_expand "vcondv8hi"
|
||||
[(set (match_operand:V4SF 0 "register_operand" "=v")
|
||||
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V8HI 2 "register_operand" "v")
|
||||
(match_operand:V8HI 3 "comparison_operator" "")
|
||||
(match_operand:V8HI 4 "register_operand" "v")
|
||||
(match_operand:V8HI 5 "register_operand" "v")
|
||||
] UNSPEC_VCOND_V8HI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"
|
||||
{
|
||||
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
|
||||
operands[3], operands[4], operands[5]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
")
|
||||
|
||||
(define_expand "vconduv8hi"
|
||||
[(set (match_operand:V4SF 0 "register_operand" "=v")
|
||||
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V8HI 2 "register_operand" "v")
|
||||
(match_operand:V8HI 3 "comparison_operator" "")
|
||||
(match_operand:V8HI 4 "register_operand" "v")
|
||||
(match_operand:V8HI 5 "register_operand" "v")
|
||||
] UNSPEC_VCONDU_V8HI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"
|
||||
{
|
||||
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
|
||||
operands[3], operands[4], operands[5]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
")
|
||||
|
||||
(define_expand "vcondv16qi"
|
||||
[(set (match_operand:V4SF 0 "register_operand" "=v")
|
||||
(unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V16QI 2 "register_operand" "v")
|
||||
(match_operand:V16QI 3 "comparison_operator" "")
|
||||
(match_operand:V16QI 4 "register_operand" "v")
|
||||
(match_operand:V16QI 5 "register_operand" "v")
|
||||
] UNSPEC_VCOND_V16QI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"
|
||||
{
|
||||
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
|
||||
operands[3], operands[4], operands[5]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
")
|
||||
|
||||
(define_expand "vconduv16qi"
|
||||
[(set (match_operand:V4SF 0 "register_operand" "=v")
|
||||
(unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V16QI 2 "register_operand" "v")
|
||||
(match_operand:V16QI 3 "comparison_operator" "")
|
||||
(match_operand:V16QI 4 "register_operand" "v")
|
||||
(match_operand:V16QI 5 "register_operand" "v")
|
||||
] UNSPEC_VCONDU_V16QI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"
|
||||
{
|
||||
if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
|
||||
operands[3], operands[4], operands[5]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
")
|
||||
|
||||
|
||||
(define_insn "altivec_vsel_4si"
|
||||
[(set (match_operand:V4SI 0 "register_operand" "=v")
|
||||
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
|
||||
(match_operand:V4SI 2 "register_operand" "v")
|
||||
(match_operand:V4SI 3 "register_operand" "v")] 159))]
|
||||
(match_operand:V4SI 3 "register_operand" "v")]
|
||||
UNSPEC_VSEL4SI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vsel %0,%1,%2,%3"
|
||||
[(set_attr "type" "vecperm")])
|
||||
|
@ -1653,7 +1825,8 @@
|
|||
[(set (match_operand:V4SF 0 "register_operand" "=v")
|
||||
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
|
||||
(match_operand:V4SF 2 "register_operand" "v")
|
||||
(match_operand:V4SI 3 "register_operand" "v")] 160))]
|
||||
(match_operand:V4SI 3 "register_operand" "v")]
|
||||
UNSPEC_VSEL4SF))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vsel %0,%1,%2,%3"
|
||||
[(set_attr "type" "vecperm")])
|
||||
|
@ -1662,7 +1835,8 @@
|
|||
[(set (match_operand:V8HI 0 "register_operand" "=v")
|
||||
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
|
||||
(match_operand:V8HI 2 "register_operand" "v")
|
||||
(match_operand:V8HI 3 "register_operand" "v")] 161))]
|
||||
(match_operand:V8HI 3 "register_operand" "v")]
|
||||
UNSPEC_VSEL8HI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vsel %0,%1,%2,%3"
|
||||
[(set_attr "type" "vecperm")])
|
||||
|
@ -1671,7 +1845,8 @@
|
|||
[(set (match_operand:V16QI 0 "register_operand" "=v")
|
||||
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
|
||||
(match_operand:V16QI 2 "register_operand" "v")
|
||||
(match_operand:V16QI 3 "register_operand" "v")] 162))]
|
||||
(match_operand:V16QI 3 "register_operand" "v")]
|
||||
UNSPEC_VSEL16QI))]
|
||||
"TARGET_ALTIVEC"
|
||||
"vsel %0,%1,%2,%3"
|
||||
[(set_attr "type" "vecperm")])
|
||||
|
|
|
@ -124,6 +124,7 @@ extern char * output_cbranch (rtx, const char *, int, rtx);
|
|||
extern char * output_e500_flip_eq_bit (rtx, rtx);
|
||||
extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
|
||||
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
|
||||
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
|
||||
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
|
||||
extern void output_toc (FILE *, rtx, int, enum machine_mode);
|
||||
extern void rs6000_initialize_trampoline (rtx, rtx, rtx);
|
||||
|
|
|
@ -760,7 +760,15 @@ static tree rs6000_build_builtin_va_list (void);
|
|||
static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *);
|
||||
static bool rs6000_must_pass_in_stack (enum machine_mode, tree);
|
||||
static bool rs6000_vector_mode_supported_p (enum machine_mode);
|
||||
static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
|
||||
enum machine_mode);
|
||||
static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
|
||||
enum machine_mode);
|
||||
static int get_vsel_insn (enum machine_mode);
|
||||
static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
|
||||
|
||||
|
||||
const int INSN_NOT_AVAILABLE = -1;
|
||||
static enum machine_mode rs6000_eh_return_filter_mode (void);
|
||||
|
||||
/* Hash table stuff for keeping track of TOC entries. */
|
||||
|
@ -11202,6 +11210,271 @@ output_e500_flip_eq_bit (rtx dst, rtx src)
|
|||
return string;
|
||||
}
|
||||
|
||||
/* Return insn index for the vector compare instruction for given CODE,
|
||||
and DEST_MODE, OP_MODE. Return INSN_NOT_AVAILABLE if valid insn is
|
||||
not available. */
|
||||
|
||||
static int
|
||||
get_vec_cmp_insn (enum rtx_code code,
|
||||
enum machine_mode dest_mode,
|
||||
enum machine_mode op_mode)
|
||||
{
|
||||
if (!TARGET_ALTIVEC)
|
||||
return INSN_NOT_AVAILABLE;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case EQ:
|
||||
if (dest_mode == V16QImode && op_mode == V16QImode)
|
||||
return UNSPEC_VCMPEQUB;
|
||||
if (dest_mode == V8HImode && op_mode == V8HImode)
|
||||
return UNSPEC_VCMPEQUH;
|
||||
if (dest_mode == V4SImode && op_mode == V4SImode)
|
||||
return UNSPEC_VCMPEQUW;
|
||||
if (dest_mode == V4SImode && op_mode == V4SFmode)
|
||||
return UNSPEC_VCMPEQFP;
|
||||
break;
|
||||
case GE:
|
||||
if (dest_mode == V4SImode && op_mode == V4SFmode)
|
||||
return UNSPEC_VCMPGEFP;
|
||||
case GT:
|
||||
if (dest_mode == V16QImode && op_mode == V16QImode)
|
||||
return UNSPEC_VCMPGTSB;
|
||||
if (dest_mode == V8HImode && op_mode == V8HImode)
|
||||
return UNSPEC_VCMPGTSH;
|
||||
if (dest_mode == V4SImode && op_mode == V4SImode)
|
||||
return UNSPEC_VCMPGTSW;
|
||||
if (dest_mode == V4SImode && op_mode == V4SFmode)
|
||||
return UNSPEC_VCMPGTFP;
|
||||
break;
|
||||
case GTU:
|
||||
if (dest_mode == V16QImode && op_mode == V16QImode)
|
||||
return UNSPEC_VCMPGTUB;
|
||||
if (dest_mode == V8HImode && op_mode == V8HImode)
|
||||
return UNSPEC_VCMPGTUH;
|
||||
if (dest_mode == V4SImode && op_mode == V4SImode)
|
||||
return UNSPEC_VCMPGTUW;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return INSN_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* Emit vector compare for operands OP0 and OP1 using code RCODE.
|
||||
DMODE is expected destination mode. This is a recursive function. */
|
||||
|
||||
static rtx
|
||||
rs6000_emit_vector_compare (enum rtx_code rcode,
|
||||
rtx op0, rtx op1,
|
||||
enum machine_mode dmode)
|
||||
{
|
||||
int vec_cmp_insn;
|
||||
rtx mask;
|
||||
enum machine_mode dest_mode;
|
||||
enum machine_mode op_mode = GET_MODE (op1);
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
if (!TARGET_ALTIVEC)
|
||||
abort ();
|
||||
|
||||
if (GET_MODE (op0) != GET_MODE (op1))
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
/* Floating point vector compare instructions uses destination V4SImode.
|
||||
Move destination to appropriate mode later. */
|
||||
if (dmode == V4SFmode)
|
||||
dest_mode = V4SImode;
|
||||
else
|
||||
dest_mode = dmode;
|
||||
|
||||
mask = gen_reg_rtx (dest_mode);
|
||||
vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
|
||||
|
||||
if (vec_cmp_insn == INSN_NOT_AVAILABLE)
|
||||
{
|
||||
bool swap_operands = false;
|
||||
bool try_again = false;
|
||||
switch (rcode)
|
||||
{
|
||||
case LT:
|
||||
rcode = GT;
|
||||
swap_operands = true;
|
||||
try_again = true;
|
||||
break;
|
||||
case LTU:
|
||||
rcode = GTU;
|
||||
swap_operands = true;
|
||||
try_again = true;
|
||||
break;
|
||||
case NE:
|
||||
/* Treat A != B as ~(A==B). */
|
||||
{
|
||||
enum insn_code nor_code;
|
||||
rtx eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
|
||||
dest_mode);
|
||||
|
||||
nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code;
|
||||
if (nor_code == CODE_FOR_nothing)
|
||||
abort ();
|
||||
emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
|
||||
|
||||
if (dmode != dest_mode)
|
||||
{
|
||||
rtx temp = gen_reg_rtx (dest_mode);
|
||||
convert_move (temp, mask, 0);
|
||||
return temp;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
break;
|
||||
case GE:
|
||||
case GEU:
|
||||
case LE:
|
||||
case LEU:
|
||||
/* Try GT/GTU/LT/LTU OR EQ */
|
||||
{
|
||||
rtx c_rtx, eq_rtx;
|
||||
enum insn_code ior_code;
|
||||
enum rtx_code new_code;
|
||||
|
||||
if (rcode == GE)
|
||||
new_code = GT;
|
||||
else if (rcode == GEU)
|
||||
new_code = GTU;
|
||||
else if (rcode == LE)
|
||||
new_code = LT;
|
||||
else if (rcode == LEU)
|
||||
new_code = LTU;
|
||||
else
|
||||
abort ();
|
||||
|
||||
c_rtx = rs6000_emit_vector_compare (new_code,
|
||||
op0, op1, dest_mode);
|
||||
eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
|
||||
dest_mode);
|
||||
|
||||
ior_code = ior_optab->handlers[(int)dest_mode].insn_code;
|
||||
if (ior_code == CODE_FOR_nothing)
|
||||
abort ();
|
||||
emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
|
||||
if (dmode != dest_mode)
|
||||
{
|
||||
rtx temp = gen_reg_rtx (dest_mode);
|
||||
convert_move (temp, mask, 0);
|
||||
return temp;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (try_again)
|
||||
{
|
||||
vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
|
||||
if (vec_cmp_insn == INSN_NOT_AVAILABLE)
|
||||
/* You only get two chances. */
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (swap_operands)
|
||||
{
|
||||
rtx tmp;
|
||||
tmp = op0;
|
||||
op0 = op1;
|
||||
op1 = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
emit_insn (gen_rtx_fmt_ee (SET,
|
||||
VOIDmode,
|
||||
mask,
|
||||
gen_rtx_fmt_Ei (UNSPEC, dest_mode,
|
||||
gen_rtvec (2, op0, op1),
|
||||
vec_cmp_insn)));
|
||||
if (dmode != dest_mode)
|
||||
{
|
||||
rtx temp = gen_reg_rtx (dest_mode);
|
||||
convert_move (temp, mask, 0);
|
||||
return temp;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if
|
||||
valid insn doesn exist for given mode. */
|
||||
|
||||
static int
|
||||
get_vsel_insn (enum machine_mode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case V4SImode:
|
||||
return UNSPEC_VSEL4SI;
|
||||
break;
|
||||
case V4SFmode:
|
||||
return UNSPEC_VSEL4SF;
|
||||
break;
|
||||
case V8HImode:
|
||||
return UNSPEC_VSEL8HI;
|
||||
break;
|
||||
case V16QImode:
|
||||
return UNSPEC_VSEL16QI;
|
||||
break;
|
||||
default:
|
||||
return INSN_NOT_AVAILABLE;
|
||||
break;
|
||||
}
|
||||
return INSN_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* Emit vector select insn where DEST is destination using
|
||||
operands OP1, OP2 and MASK. */
|
||||
|
||||
static void
|
||||
rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
|
||||
{
|
||||
rtx t, temp;
|
||||
enum machine_mode dest_mode = GET_MODE (dest);
|
||||
int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
|
||||
|
||||
temp = gen_reg_rtx (dest_mode);
|
||||
|
||||
t = gen_rtx_fmt_ee (SET, VOIDmode, temp,
|
||||
gen_rtx_fmt_Ei (UNSPEC, dest_mode,
|
||||
gen_rtvec (3, op1, op2, mask),
|
||||
vsel_insn_index));
|
||||
emit_insn (t);
|
||||
emit_move_insn (dest, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Emit vector conditional expression.
|
||||
DEST is destination. OP1 and OP2 are two VEC_COND_EXPR operands.
|
||||
CC_OP0 and CC_OP1 are the two operands for the relation operation COND. */
|
||||
|
||||
int
|
||||
rs6000_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2,
|
||||
rtx cond, rtx cc_op0, rtx cc_op1)
|
||||
{
|
||||
enum machine_mode dest_mode = GET_MODE (dest);
|
||||
enum rtx_code rcode = GET_CODE (cond);
|
||||
rtx mask;
|
||||
|
||||
if (!TARGET_ALTIVEC)
|
||||
return 0;
|
||||
|
||||
/* Get the vector mask for the given relational operations. */
|
||||
mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
|
||||
|
||||
rs6000_emit_vector_select (dest, op1, op2, mask);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Emit a conditional move: move TRUE_COND to DEST if OP of the
|
||||
operands of the last comparison is nonzero/true, FALSE_COND if it
|
||||
is zero/false. Return 0 if the hardware has no such operation. */
|
||||
|
|
Loading…
Reference in New Issue