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:
Devang Patel 2004-10-07 09:05:35 -07:00 committed by Devang Patel
parent 03d3f46d57
commit 21213b4c93
4 changed files with 485 additions and 17 deletions

View File

@ -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

View File

@ -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")])

View File

@ -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);

View File

@ -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. */