===================================================================
@@ -566,7 +566,9 @@ (define_code_iterator any_fix [fix unsi
(define_code_iterator any_float [float unsigned_float])
(define_code_attr u [(sign_extend "")
- (zero_extend "u")])
+ (zero_extend "u")
+ (fix "")
+ (unsigned_fix "u")])
(define_code_attr su [(sign_extend "s")
(zero_extend "u")
@@ -1027,8 +1029,8 @@ (define_insn_and_split "*extendhi<mode>2
(define_insn "extendsi<mode>2"
- [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,wl,wu,wj,wK")
- (sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" "Y,r,Z,Z,r,wK")))]
+ [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,wl,wu,wj,wK,wH")
+ (sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" "Y,r,Z,Z,r,wK,wH")))]
""
"@
lwa%U1%X1 %0,%1
@@ -1036,9 +1038,38 @@ (define_insn "extendsi<mode>2"
lfiwax %0,%y1
lxsiwax %x0,%y1
mtvsrwa %x0,%1
- vextsw2d %0,%1"
- [(set_attr "type" "load,exts,fpload,fpload,mffgpr,vecexts")
- (set_attr "sign_extend" "yes")])
+ vextsw2d %0,%1
+ #"
+ [(set_attr "type" "load,exts,fpload,fpload,mffgpr,vecexts,vecperm")
+ (set_attr "sign_extend" "yes")
+ (set_attr "length" "4,4,4,4,4,4,8")])
+
+(define_split
+ [(set (match_operand:DI 0 "altivec_register_operand")
+ (sign_extend:DI (match_operand:SI 1 "altivec_register_operand")))]
+ "TARGET_VSX_SMALL_INTEGER && TARGET_P8_VECTOR && !TARGET_P9_VECTOR
+ && reload_completed"
+ [(const_int 0)]
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ int dest_regno = REGNO (dest);
+ int src_regno = REGNO (src);
+ rtx dest_v2di = gen_rtx_REG (V2DImode, dest_regno);
+ rtx src_v4si = gen_rtx_REG (V4SImode, src_regno);
+
+ if (VECTOR_ELT_ORDER_BIG)
+ {
+ emit_insn (gen_altivec_vupkhsw (dest_v2di, src_v4si));
+ emit_insn (gen_vsx_xxspltd_v2di (dest_v2di, dest_v2di, const1_rtx));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vupklsw (dest_v2di, src_v4si));
+ emit_insn (gen_vsx_xxspltd_v2di (dest_v2di, dest_v2di, const0_rtx));
+ }
+ DONE;
+})
(define_insn_and_split "*extendsi<mode>2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
@@ -5570,7 +5601,7 @@ (define_expand "fix_trunc<mode>si2"
"TARGET_HARD_FLOAT && ((TARGET_FPRS && <TARGET_FLOAT>) || <E500_CONVERT>)"
"
{
- if (!<E500_CONVERT>)
+ if (!<E500_CONVERT> && !TARGET_VSX_SMALL_INTEGER)
{
rtx src = force_reg (<MODE>mode, operands[1]);
@@ -5596,7 +5627,8 @@ (define_insn_and_split "fix_trunc<mode>s
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
- && TARGET_STFIWX && can_create_pseudo_p ()"
+ && TARGET_STFIWX && can_create_pseudo_p ()
+ && !TARGET_VSX_SMALL_INTEGER"
"#"
""
[(pc)]
@@ -5637,7 +5669,8 @@ (define_insn_and_split "fix_trunc<mode>s
(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,<rreg>")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=1,d"))
(clobber (match_operand:DI 3 "offsettable_mem_operand" "=o,o"))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !TARGET_VSX_SMALL_INTEGER"
"#"
""
[(pc)]
@@ -5721,7 +5754,7 @@ (define_expand "fixuns_trunc<mode>si2"
|| <E500_CONVERT>)"
"
{
- if (!<E500_CONVERT>)
+ if (!<E500_CONVERT> && !TARGET_VSX_SMALL_INTEGER)
{
emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1]));
DONE;
@@ -5733,7 +5766,8 @@ (define_insn_and_split "fixuns_trunc<mod
(unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
- && TARGET_STFIWX && can_create_pseudo_p ()"
+ && TARGET_STFIWX && can_create_pseudo_p ()
+ && !TARGET_VSX_SMALL_INTEGER"
"#"
""
[(pc)]
@@ -5818,13 +5852,43 @@ (define_insn_and_split "*fixuns_trunc<SF
}
DONE;
})
-; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
-; rather than (set (subreg:SI (reg)) (fix:SI ...))
-; because the first makes it clear that operand 0 is not live
-; before the instruction.
+
+;; If -mvsx-small-integer, we can represent the FIX operation directly. On
+;; older machines, we have to use an UNSPEC to produce a SImode and move it
+;; to another location, since SImode is not allowed in vector registers.
+(define_insn "*fctiw<u>z_<mode>_smallint"
+ [(set (match_operand:SI 0 "vsx_register_operand" "=d,wi")
+ (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && TARGET_VSX_SMALL_INTEGER"
+ "@
+ fctiw<u>z %0,%1
+ xscvdp<su>xws %x0,%x1"
+ [(set_attr "type" "fp")])
+
+;; Combiner pattern to prevent moving the result of converting a floating point
+;; value to 32-bit integer to GPR in order to save it.
+(define_insn_and_split "*fctiw<u>z_<mode>_mem"
+ [(set (match_operand:SI 0 "memory_operand" "=Z")
+ (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "wa")))
+ (clobber (match_scratch:SI 2 "=wa"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && TARGET_VSX_SMALL_INTEGER"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (any_fix:SI (match_dup 1)))
+ (set (match_dup 0)
+ (match_dup 2))])
+
+;; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
+;; rather than (set (subreg:SI (reg)) (fix:SI ...))
+;; because the first makes it clear that operand 0 is not live
+;; before the instruction.
(define_insn "fctiwz_<mode>"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
- (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
+ (unspec:DI [(fix:SI
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
UNSPEC_FCTIWZ))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"@
===================================================================
@@ -3,18 +3,21 @@
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
/* { dg-options "-O2 -mcpu=power8" } */
-/* { dg-final { scan-assembler-times "fcfid " 2 } } */
-/* { dg-final { scan-assembler-times "fcfids " 2 } } */
-/* { dg-final { scan-assembler-times "fctiwuz \|xscvdpuxws " 2 } } */
+/* { dg-final { scan-assembler-times "fcfid \|xscvsxddp " 2 } } */
+/* { dg-final { scan-assembler-times "fcfids \|xscvsxdsp " 2 } } */
/* { dg-final { scan-assembler-times "fctiwz \|xscvdpsxws " 2 } } */
-/* { dg-final { scan-assembler-times "mfvsrd " 4 } } */
-/* { dg-final { scan-assembler-times "mtvsrwa " 2 } } */
-/* { dg-final { scan-assembler-times "mtvsrwz " 2 } } */
-/* { dg-final { scan-assembler-not "lwz" } } */
-/* { dg-final { scan-assembler-not "lfiwax " } } */
-/* { dg-final { scan-assembler-not "lfiwzx " } } */
-/* { dg-final { scan-assembler-not "stw" } } */
-/* { dg-final { scan-assembler-not "stfiwx " } } */
+/* { dg-final { scan-assembler-times "fctiwuz \|xscvdpuxws " 2 } } */
+/* { dg-final { scan-assembler-times {\mmfvsrwz\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mmtvsrwz\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvupkhsw\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxpermdi\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mmfvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mmtvsrwa\M} } } */
+/* { dg-final { scan-assembler-not {\mlwz\M} } } */
+/* { dg-final { scan-assembler-not {\mlfiwax\M} } } */
+/* { dg-final { scan-assembler-not {\mlfiwzx\M} } } */
+/* { dg-final { scan-assembler-not {\mstw\M} } } */
+/* { dg-final { scan-assembler-not {\mstfiwx\M} } } */
/* Make sure we don't have loads/stores to the GPR unit. */
double
===================================================================
@@ -0,0 +1,45 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -mcpu=power9" } */
+/* { dg-final { scan-assembler-times "fcfid \|xscvsxddp " 2 } } */
+/* { dg-final { scan-assembler-times "fcfids \|xscvsxdsp " 2 } } */
+/* { dg-final { scan-assembler-times "fctiwz \|xscvdpsxws " 2 } } */
+/* { dg-final { scan-assembler-times "fctiwuz \|xscvdpuxws " 2 } } */
+/* { dg-final { scan-assembler-times {\mvextsw2d\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxextractuw\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mmfvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mmfvsrwz\M} } } */
+/* { dg-final { scan-assembler-not {\mmtvsrwa\M} } } */
+/* { dg-final { scan-assembler-not {\mmtvsrwz\M} } } */
+/* { dg-final { scan-assembler-not {\mlwz\M} } } */
+/* { dg-final { scan-assembler-not {\mlfiwax\M} } } */
+/* { dg-final { scan-assembler-not {\mlfiwzx\M} } } */
+/* { dg-final { scan-assembler-not {\mstw\M} } } */
+/* { dg-final { scan-assembler-not {\mstfiwx\M} } } */
+
+/* Make sure we don't have loads/stores to the GPR unit. */
+double
+round_double_int (double a)
+{
+ return (double)(int)a;
+}
+
+float
+round_float_int (float a)
+{
+ return (float)(int)a;
+}
+
+double
+round_double_uint (double a)
+{
+ return (double)(unsigned int)a;
+}
+
+float
+round_float_uint (float a)
+{
+ return (float)(unsigned int)a;
+}