summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/altivec.h8
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def23
-rw-r--r--gcc/config/rs6000/rs6000-c.c23
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c29
-rw-r--r--gcc/config/rs6000/vsx.md194
6 files changed, 278 insertions, 0 deletions
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index dd68ae10e5a..53d8c47c2aa 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -182,6 +182,14 @@
#define vec_rlnm(a,b,c) (__builtin_vec_rlnm((a),((b)<<8)|(c)))
#define vec_rsqrt __builtin_vec_rsqrt
#define vec_rsqrte __builtin_vec_rsqrte
+#define vec_signed __builtin_vec_vsigned
+#define vec_signed2 __builtin_vec_vsigned2
+#define vec_signede __builtin_vec_vsignede
+#define vec_signedo __builtin_vec_vsignedo
+#define vec_unsigned __builtin_vec_vunsigned
+#define vec_unsigned2 __builtin_vec_vunsigned2
+#define vec_unsignede __builtin_vec_vunsignede
+#define vec_unsignedo __builtin_vec_vunsignedo
#define vec_vsubfp __builtin_vec_vsubfp
#define vec_subc __builtin_vec_subc
#define vec_vsubsws __builtin_vec_vsubsws
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 0e7621cf1ca..afec0145543 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -1611,6 +1611,9 @@ BU_VSX_2 (CMPLE_U2DI, "cmple_u2di", CONST, vector_ngtuv2di)
BU_VSX_2 (FLOAT2_V2DI, "float2_v2di", CONST, float2_v2di)
BU_VSX_2 (UNS_FLOAT2_V2DI, "uns_float2_v2di", CONST, uns_float2_v2di)
+BU_VSX_2 (VEC_VSIGNED2_V2DF, "vsigned2_v2df", CONST, vsigned2_v2df)
+BU_VSX_2 (VEC_VUNSIGNED2_V2DF, "vunsigned2_v2df", CONST, vunsigned2_v2df)
+
/* VSX abs builtin functions. */
BU_VSX_A (XVABSDP, "xvabsdp", CONST, absv2df2)
BU_VSX_A (XVNABSDP, "xvnabsdp", CONST, vsx_nabsv2df2)
@@ -1702,6 +1705,16 @@ BU_VSX_1 (DOUBLEL_V4SI, "doublel_v4si", CONST, doublelv4si2)
BU_VSX_1 (DOUBLEL_V4SF, "doublel_v4sf", CONST, doublelv4sf2)
BU_VSX_1 (UNS_DOUBLEL_V4SI, "uns_doublel_v4si", CONST, unsdoublelv4si2)
+BU_VSX_1 (VEC_VSIGNED_V4SF, "vsigned_v4sf", CONST, vsx_xvcvspsxws)
+BU_VSX_1 (VEC_VSIGNED_V2DF, "vsigned_v2df", CONST, vsx_xvcvdpsxds)
+BU_VSX_1 (VEC_VSIGNEDE_V2DF, "vsignede_v2df", CONST, vsignede_v2df)
+BU_VSX_1 (VEC_VSIGNEDO_V2DF, "vsignedo_v2df", CONST, vsignedo_v2df)
+
+BU_VSX_1 (VEC_VUNSIGNED_V4SF, "vunsigned_v4sf", CONST, vsx_xvcvspsxws)
+BU_VSX_1 (VEC_VUNSIGNED_V2DF, "vunsigned_v2df", CONST, vsx_xvcvdpsxds)
+BU_VSX_1 (VEC_VUNSIGNEDE_V2DF, "vunsignede_v2df", CONST, vunsignede_v2df)
+BU_VSX_1 (VEC_VUNSIGNEDO_V2DF, "vunsignedo_v2df", CONST, vunsignedo_v2df)
+
/* VSX predicate functions. */
BU_VSX_P (XVCMPEQSP_P, "xvcmpeqsp_p", CONST, vector_eq_v4sf_p)
BU_VSX_P (XVCMPGESP_P, "xvcmpgesp_p", CONST, vector_ge_v4sf_p)
@@ -1791,6 +1804,8 @@ BU_VSX_OVERLOAD_2 (XXSPLTD, "xxspltd")
BU_VSX_OVERLOAD_2 (XXSPLTW, "xxspltw")
BU_VSX_OVERLOAD_2 (FLOAT2, "float2")
BU_VSX_OVERLOAD_2 (UNS_FLOAT2, "uns_float2")
+BU_VSX_OVERLOAD_2 (VSIGNED2, "vsigned2")
+BU_VSX_OVERLOAD_2 (VUNSIGNED2, "vunsigned2")
/* 1 argument VSX overloaded builtin functions. */
BU_VSX_OVERLOAD_1 (DOUBLE, "double")
@@ -1806,6 +1821,14 @@ BU_VSX_OVERLOAD_1 (FLOAT, "float")
BU_VSX_OVERLOAD_1 (FLOATE, "floate")
BU_VSX_OVERLOAD_1 (FLOATO, "floato")
+BU_VSX_OVERLOAD_1 (VSIGNED, "vsigned")
+BU_VSX_OVERLOAD_1 (VSIGNEDE, "vsignede")
+BU_VSX_OVERLOAD_1 (VSIGNEDO, "vsignedo")
+
+BU_VSX_OVERLOAD_1 (VUNSIGNED, "vunsigned")
+BU_VSX_OVERLOAD_1 (VUNSIGNEDE, "vunsignede")
+BU_VSX_OVERLOAD_1 (VUNSIGNEDO, "vunsignedo")
+
/* VSX builtins that are handled as special cases. */
BU_VSX_OVERLOAD_X (LD, "ld")
BU_VSX_OVERLOAD_X (ST, "st")
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index fdf18fda553..6293308ede0 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -5550,6 +5550,29 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V16QI,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNED, VSX_BUILTIN_VEC_VSIGNED_V4SF,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNED, VSX_BUILTIN_VEC_VSIGNED_V2DF,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNEDE, VSX_BUILTIN_VEC_VSIGNEDE_V2DF,
+ RS6000_BTI_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNEDO, VSX_BUILTIN_VEC_VSIGNEDO_V2DF,
+ RS6000_BTI_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNED2, VSX_BUILTIN_VEC_VSIGNED2_V2DF,
+ RS6000_BTI_V4SI, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+
+ { VSX_BUILTIN_VEC_VUNSIGNED, VSX_BUILTIN_VEC_VUNSIGNED_V4SF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNED, VSX_BUILTIN_VEC_VUNSIGNED_V2DF,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNEDE, VSX_BUILTIN_VEC_VUNSIGNEDE_V2DF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNEDO, VSX_BUILTIN_VEC_VUNSIGNEDO_V2DF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNED2, VSX_BUILTIN_VEC_VUNSIGNED2_V2DF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V2DF,
+ RS6000_BTI_V2DF, 0 },
+
/* Crypto builtins. */
{ CRYPTO_BUILTIN_VPERMXOR, CRYPTO_BUILTIN_VPERMXOR_V16QI,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index e3132049270..44fdf8ae09c 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -73,6 +73,7 @@ extern void rs6000_expand_extract_even (rtx, rtx, rtx);
extern void rs6000_expand_interleave (rtx, rtx, rtx, bool);
extern void rs6000_scale_v2df (rtx, rtx, int);
extern void rs6000_generate_float2_code (bool, rtx, rtx, rtx);
+extern void rs6000_generate_vsigned2_code (bool, rtx, rtx, rtx);
extern int expand_block_clear (rtx[]);
extern int expand_block_move (rtx[]);
extern bool expand_block_compare (rtx[]);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 79dccba1dce..181794d8dad 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -41074,6 +41074,35 @@ rs6000_generate_float2_code (bool signed_convert, rtx dst, rtx src1, rtx src2)
emit_insn (gen_p8_vmrgew_v4sf (dst, rtx_tmp3, rtx_tmp2));
}
+void
+rs6000_generate_vsigned2_code (bool signed_convert, rtx dst, rtx src1,
+ rtx src2)
+{
+ rtx rtx_tmp0, rtx_tmp1, rtx_tmp2, rtx_tmp3;
+
+ rtx_tmp0 = gen_reg_rtx (V2DFmode);
+ rtx_tmp1 = gen_reg_rtx (V2DFmode);
+
+ emit_insn (gen_vsx_xxpermdi_v2df (rtx_tmp0, src1, src2, GEN_INT (0)));
+ emit_insn (gen_vsx_xxpermdi_v2df (rtx_tmp1, src1, src2, GEN_INT (3)));
+
+ rtx_tmp2 = gen_reg_rtx (V4SImode);
+ rtx_tmp3 = gen_reg_rtx (V4SImode);
+
+ if (signed_convert)
+ {
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp2, rtx_tmp0));
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp3, rtx_tmp1));
+ }
+ else
+ {
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp2, rtx_tmp0));
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp3, rtx_tmp1));
+ }
+
+ emit_insn (gen_p8_vmrgew_v4si (dst, rtx_tmp2, rtx_tmp3));
+}
+
/* Implement the TARGET_OPTAB_SUPPORTED_P hook. */
static bool
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 4d73f0abe0a..2ddfae537c9 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -358,6 +358,8 @@
UNSPEC_VSX_XVCVDPSXDS
UNSPEC_VSX_XVCVDPUXDS
UNSPEC_VSX_SIGN_EXTEND
+ UNSPEC_VSX_XVCVSPSXWS
+ UNSPEC_VSX_XVCVSPSXDS
UNSPEC_VSX_VSLO
UNSPEC_VSX_EXTRACT
UNSPEC_VSX_SXEXPDP
@@ -370,6 +372,7 @@
UNSPEC_VSX_VIEXP
UNSPEC_VSX_VTSTDC
UNSPEC_VSX_VEC_INIT
+ UNSPEC_VSX_VSIGNED2
UNSPEC_LXVL
UNSPEC_STXVL
UNSPEC_VCLZLSBB
@@ -1864,6 +1867,8 @@
DONE;
})
+;; convert vector of 64-bit floating point numbers to vector of
+;; 64-bit signed integer
(define_insn "vsx_xvcvdpsxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
(unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
@@ -1872,6 +1877,18 @@
"xvcvdpsxds %x0,%x1"
[(set_attr "type" "vecdouble")])
+;; convert vector of 32-bit floating point numbers to vector of
+;; 32-bit signed integer
+(define_insn "vsx_xvcvspsxws"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
+ (unspec:V4SI [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
+ UNSPEC_VSX_XVCVSPSXWS))]
+ "VECTOR_UNIT_VSX_P (V4SFmode)"
+ "xvcvspsxws %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+;; convert vector of 64-bit floating point numbers to vector of
+;; 64-bit unsigned integer
(define_expand "vsx_xvcvdpuxds_scale"
[(match_operand:V2DI 0 "vsx_register_operand" "")
(match_operand:V2DF 1 "vsx_register_operand" "")
@@ -1893,6 +1910,16 @@
DONE;
})
+;; convert vector of 32-bit floating point numbers to vector of
+;; 32-bit unsigned integer
+(define_insn "vsx_xvcvspuxws"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
+ (unspec:V4SI [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
+ UNSPEC_VSX_XVCVSPSXWS))]
+ "VECTOR_UNIT_VSX_P (V4SFmode)"
+ "xvcvspuxws %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
(define_insn "vsx_xvcvdpuxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
(unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
@@ -2137,6 +2164,173 @@
DONE;
})
+;; Generate vsigned2
+;; convert two double float vectors to a vector of single precision ints
+(define_expand "vsigned2_v2df"
+ [(match_operand:V4SI 0 "register_operand" "=wa")
+ (unspec:V4SI [(match_operand:V2DF 1 "register_operand" "wa")
+ (match_operand:V2DF 2 "register_operand" "wa")]
+ UNSPEC_VSX_VSIGNED2)]
+ "TARGET_VSX"
+{
+ rtx rtx_src1, rtx_src2, rtx_dst;
+ bool signed_convert=true;
+
+ rtx_dst = operands[0];
+ rtx_src1 = operands[1];
+ rtx_src2 = operands[2];
+
+ rs6000_generate_vsigned2_code (signed_convert, rtx_dst, rtx_src1, rtx_src2);
+ DONE;
+})
+
+;; Generate vsignedo_v2df
+;; signed double float to int convert odd word
+(define_expand "vsignedo_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=wa")
+ (match_operand:V2DF 1 "register_operand" "wa"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp, operands[1]));
+
+ /* Big endian word numbering for words in operand is 0 1 2 3.
+ take (operand[1] operand[1]) and shift left one word
+ 0 1 2 3 0 1 2 3 => 1 2 3 0
+ Words 1 and 3 are now are now where they need to be for result. */
+
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ else
+ /* Little endian word numbering for operand is 3 2 1 0.
+ Result words 3 and 1 are where they need to be. */
+ emit_insn (gen_vsx_xvcvdpsxws (operands[0], operands[1]));
+
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
+;; Generate vsignede_v2df
+;; signed double float to int even word
+(define_expand "vsignede_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (match_operand:V2DF 1 "register_operand" "v"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ /* Big endian word numbering for words in operand is 0 1
+ Result words 0 is where they need to be. */
+ emit_insn (gen_vsx_xvcvdpsxws (operands[0], operands[1]));
+
+ else
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp, operands[1]));
+
+ /* Little endian word numbering for operand is 3 2 1 0.
+ take (operand[1] operand[1]) and shift left three words
+ 0 1 2 3 0 1 2 3 => 3 0 1 2
+ Words 0 and 2 are now where they need to be for the result. */
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
+;; Generate unsigned2
+;; convert two double float vectors to a vector of single precision
+;; unsigned ints
+(define_expand "vunsigned2_v2df"
+[(match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V2DF 1 "register_operand" "v")
+ (match_operand:V2DF 2 "register_operand" "v")]
+ UNSPEC_VSX_VSIGNED2)]
+ "TARGET_VSX"
+{
+ rtx rtx_src1, rtx_src2, rtx_dst;
+ bool signed_convert=false;
+
+ rtx_dst = operands[0];
+ rtx_src1 = operands[1];
+ rtx_src2 = operands[2];
+
+ rs6000_generate_vsigned2_code (signed_convert, rtx_dst, rtx_src1, rtx_src2);
+ DONE;
+})
+
+;; Generate vunsignedo_v2df
+;; unsigned double float to int convert odd word
+(define_expand "vunsignedo_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (match_operand:V2DF 1 "register_operand" "v"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp, operands[1]));
+
+ /* Big endian word numbering for words in operand is 0 1 2 3.
+ take (operand[1] operand[1]) and shift left one word
+ 0 1 2 3 0 1 2 3 => 1 2 3 0
+ Words 1 and 3 are now are now where they need to be for result. */
+
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ else
+ /* Little endian word numbering for operand is 3 2 1 0.
+ Result words 3 and 1 are where they need to be. */
+ emit_insn (gen_vsx_xvcvdpuxws (operands[0], operands[1]));
+
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
+;; Generate vunsignede_v2df
+;; unsigned double float to int even word
+(define_expand "vunsignede_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (match_operand:V2DF 1 "register_operand" "v"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ /* Big endian word numbering for words in operand is 0 1
+ Result words 0 is where they need to be. */
+ emit_insn (gen_vsx_xvcvdpuxws (operands[0], operands[1]));
+
+ else
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp, operands[1]));
+
+ /* Little endian word numbering for operand is 3 2 1 0.
+ take (operand[1] operand[1]) and shift left three words
+ 0 1 2 3 0 1 2 3 => 3 0 1 2
+ Words 0 and 2 are now where they need to be for the result. */
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
;; since the xvrdpiz instruction does not truncate the value if the floating
;; point value is < LONG_MIN or > LONG_MAX.