Improve floating point conversions on powerpc

From-SVN: r163598
This commit is contained in:
Michael Meissner 2010-08-27 21:32:44 +00:00 committed by Michael Meissner
parent a3c85b7499
commit 7042fe5ef8
16 changed files with 1187 additions and 213 deletions

View File

@ -1,3 +1,123 @@
2010-08-23 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000-protos.h (rs6000_address_for_fpconvert):
New declaration.
(rs6000_allocate_stack_temp): Ditto.
(rs6000_expand_convert_si_to_sfdf): Ditto.
* config/rs6000/rs6000.c (rs6000_override_options): Adjust long
line. Update the options set if power6 or power7 server/embedded
type options are used. If we give a warning for no vsx under
-mcpu=power7 -mno-altivec, mark -mvsx as an explicit option.
(rs6000_allocate_stack_temp): New function to allocate a stack
tempoary and adjust the address so it meets either REG+OFFSET or
REG+REG addressing requirements.
(rs6000_address_for_fpconvert): Adjust REG+OFFSET addresses so
that they can be used with the LFIWAX/LFIWZX instrucitons.
(rs6000_expand_convert_si_to_sfdf): New helper funciton for
converting signed/unsigned SImode to either SFmode/DFmode.
* config/rs6000/rs6000.h (TARGET_FCFID): New macros to determine
whether certain instructions can be generated.
(TARGET_FCTIDZ): Ditto.
(TARGET_STFIWX): Ditto.
(TARGET_LFIWAX): Ditto.
(TARGET_LFIWZX): Ditto.
(TARGET_FCFIDS): Ditto.
(TARGET_FCFIDU): Ditto.
(TARGET_FCFIDUS): Ditto.
(TARGET_FCTIDUZ): Ditto.
(TARGET_FCTIWUZ): Ditto.
* config/rs6000/rs6000.md (UNSPEC_FCTIW): New unspec constants.
(UNSPEC_FCTID): Ditto.
(UNSPEC_LFIWAX): Ditto.
(UNSPEC_LFIWZX): Ditto.
(UNSPEC_FCTIWUZ): Ditto.
(rreg): Use correct constraints.
(SI_CONVERT_FP): New mode attribute for floating point conversion
tests.
(E500_CONVERT): Ditto.
(lfiwax): New insns for converting from integer to floating point
utilizing newer instructions. Attempt to optimize conversions
that come from memory so that we don't load the value into a GPR,
spill it to the stack and reload it into a FPR.
(floatsi<mode>2_lfiwax): Ditto.
(floatsi<mode>2_lfiwax_mem): Ditto.
(floatsi<mode>2_lfiwax_mem2): Ditto.
(lfiwzx): Ditto.
(floatunssi<mode>2_lfiwzx): Ditto.
(floatunssi<mode>2_lfiwzx_mem): Ditto.
(floatunssi<mode>2_lfiwzx_mem2): Ditto.
(floatdidf2_mem): Ditto.
(floatunsdidf2_fcfidu): Ditto.
(floatunsdidf2_mem): Ditto.
(floatunsdisf2): Ditto.
(floatunsdisf2_fcfidus): Ditto.
(floatunsdisf2_mem): Ditto.
(floatsidf2): Add support for LFIWAX/LFIWZX/FCFIDS/FCFIDU/FCFIDUS.
Use FCFID on 32-bit hosts that support it.
(floatsidf2_internal): Ditto.
(floatunssisf2): Ditto.
(floatunssidf2): Ditto.
(floatunssidf2_internal): Ditto.
(floatsisf2): Ditto.
(floatdidf2): Ditto.
(floatdidf2_fpr): Ditto.
(floatunsdidf2): Ditto.
(floatdisf2): Ditto.
(floatdisf2_fcfids): Ditto.
(floatdisf2_internal1): Ditto.
(fixuns_truncsfsi2): Delete, merge into common pattern for both
SF/DF. Add power7 support.
(fix_truncsfsi2): Ditto.
(fixuns_truncdfsi2): Ditto.
(fixuns_truncdfdi2): Ditto.
(fix_truncdfsi2): Ditto.
(fix_truncdfsi2_internal): Ditto.
(fix_truncdfsi2_internal_gfxopt): Ditto.
(fix_truncdfsi2_mfpgpr): Ditto.
(fctiwz): Ditto.
(btruncdf2): Ditto.
(btruncdf2_fpr): Ditto.
(btructsf2): Ditto.
(ceildf2): Ditto.
(ceildf2_fpr): Ditto.
(ceilsf2): Ditto.
(floordf2): Ditto.
(floordf2_fpr): Ditto.
(floorsf2): Ditto.
(rounddf2): Ditto.
(rounddf2_fpr): Ditto.
(roundsf2): Ditto.
(fix_trunc<mode>si2): Combine SF/DF conversion into one insn.
(fix_trunc<mode>di2): Ditto.
(fixuns_trunc<mode>si2): Ditto.
(fixuns_trunc<mode>di2): Ditto.
(fctiwz_<mode>): Ditto.
(btrunc<mode>2): Ditto.
(btrunc<mode>2_fpr): Ditto.
(ceil<mode>2): Ditto.
(ceil<mode>2_fpr): Ditto.
(floor<mode>2): Ditto.
(float<mode>2_fpr): Ditto.
(round<mode>2): Ditto.
(round<mode>2_fpr): Ditto.
(fix_trunc<mode>si2_stfiwx): New insn for machines with STFIWX.
(fixuns_trunc<mode>si2_stfiwx): Ditto.
(fix_truncdfsi2_internal): Ditto.
(fix_trunc<mode>si2_mem): Combiner pattern to eliminate storing
converted value on stack, loaded into GPR, and then stored into
the final destination.
(fix_trunc<mode>di2_fctidz): New pattern for targets supporting
FCTIDZ.
(lrint<mode>di2): New insn, provide the lrint builtin functions.
(ftruncdf2): Delete, unused.
(fix_trunctfsi2_internal): Use gen_fctiwz_df, not gen_fctiwz.
* config/rs6000/vsx.md (toplevel): Update copyright year.
(VSr2): Use "ws" contraint for DFmode, not "!r#r".
(VSr3): Ditto.
2010-08-27 Basile Starynkevitch <basile@starynkevitch.net>
Jeremie Salvucci <jeremie.salvucci@free.fr>

View File

@ -129,6 +129,9 @@ extern void rs6000_emit_parity (rtx, rtx);
extern rtx rs6000_machopic_legitimize_pic_address (rtx, enum machine_mode,
rtx);
extern rtx rs6000_address_for_fpconvert (rtx);
extern rtx rs6000_allocate_stack_temp (enum machine_mode, bool, bool);
extern void rs6000_expand_convert_si_to_sfdf (rtx, rtx, bool);
#endif /* RTX_CODE */
#ifdef TREE_CODE

View File

@ -2510,10 +2510,10 @@ rs6000_override_options (const char *default_cpu)
POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
| MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
| MASK_MFPGPR | MASK_RECIP_PRECISION},
{"power7", PROCESSOR_POWER7,
{"power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */
POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
| MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
| MASK_VSX| MASK_RECIP_PRECISION}, /* Don't add MASK_ISEL by default */
| MASK_VSX | MASK_RECIP_PRECISION},
{"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
{"powerpc64", PROCESSOR_POWERPC64,
POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
@ -2550,15 +2550,19 @@ rs6000_override_options (const char *default_cpu)
ISA_2_1_MASKS = MASK_MFCRF,
ISA_2_2_MASKS = (ISA_2_1_MASKS | MASK_POPCNTB | MASK_FPRND),
/* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and
don't add ALTIVEC, since in general it isn't a win on power6. */
ISA_2_5_MASKS = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION
| MASK_DFP),
/* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't
add ALTIVEC, since in general it isn't a win on power6. In ISA 2.04,
fsel, fre, fsqrt, etc. were no longer documented as optional. Group
masks by server and embedded. */
ISA_2_5_MASKS_EMBEDDED = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION
| MASK_PPC_GFXOPT | MASK_PPC_GPOPT),
ISA_2_5_MASKS_SERVER = (ISA_2_5_MASKS_EMBEDDED | MASK_DFP),
/* For ISA 2.06, don't add ISEL, since in general it isn't a win, but
altivec is a win so enable it. */
ISA_2_6_MASKS = (ISA_2_5_MASKS | MASK_ALTIVEC | MASK_POPCNTD
| MASK_VSX | MASK_RECIP_PRECISION)
ISA_2_6_MASKS_EMBEDDED = (ISA_2_5_MASKS_EMBEDDED | MASK_POPCNTD),
ISA_2_6_MASKS_SERVER = (ISA_2_5_MASKS_SERVER | MASK_POPCNTD | MASK_ALTIVEC
| MASK_VSX)
};
/* Numerous experiment shows that IRA based loop pressure
@ -2699,15 +2703,22 @@ rs6000_override_options (const char *default_cpu)
{
warning (0, msg);
target_flags &= ~ MASK_VSX;
target_flags_explicit |= MASK_VSX;
}
}
/* For the newer switches (vsx, dfp, etc.) set some of the older options,
unless the user explicitly used the -mno-<option> to disable the code. */
if (TARGET_VSX)
target_flags |= (ISA_2_6_MASKS & ~target_flags_explicit);
target_flags |= (ISA_2_6_MASKS_SERVER & ~target_flags_explicit);
else if (TARGET_POPCNTD)
target_flags |= (ISA_2_6_MASKS_EMBEDDED & ~target_flags_explicit);
else if (TARGET_DFP)
target_flags |= (ISA_2_5_MASKS & ~target_flags_explicit);
target_flags |= (ISA_2_5_MASKS_SERVER & ~target_flags_explicit);
else if (TARGET_CMPB)
target_flags |= (ISA_2_5_MASKS_EMBEDDED & ~target_flags_explicit);
else if (TARGET_POPCNTB || TARGET_FPRND)
target_flags |= (ISA_2_2_MASKS & ~target_flags_explicit);
else if (TARGET_ALTIVEC)
target_flags |= (MASK_PPC_GFXOPT & ~target_flags_explicit);
@ -26959,4 +26970,122 @@ rs6000_final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
}
}
/* Allocate a stack temp and fixup the address so it meets the particular
memory requirements (either offetable or REG+REG addressing). */
rtx
rs6000_allocate_stack_temp (enum machine_mode mode,
bool offsettable_p,
bool reg_reg_p)
{
rtx stack = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
rtx addr = XEXP (stack, 0);
int strict_p = (reload_in_progress || reload_completed);
if (!legitimate_indirect_address_p (addr, strict_p))
{
if (offsettable_p
&& !rs6000_legitimate_offset_address_p (mode, addr, strict_p))
stack = replace_equiv_address (stack, copy_addr_to_reg (addr));
else if (reg_reg_p && !legitimate_indexed_address_p (addr, strict_p))
stack = replace_equiv_address (stack, copy_addr_to_reg (addr));
}
return stack;
}
/* Given a memory reference, if it is not a reg or reg+reg addressing, convert
to such a form to deal with memory reference instructions like STFIWX that
only take reg+reg addressing. */
rtx
rs6000_address_for_fpconvert (rtx x)
{
int strict_p = (reload_in_progress || reload_completed);
rtx addr;
gcc_assert (MEM_P (x));
addr = XEXP (x, 0);
if (! legitimate_indirect_address_p (addr, strict_p)
&& ! legitimate_indexed_address_p (addr, strict_p))
x = replace_equiv_address (x, copy_addr_to_reg (addr));
return x;
}
/* Expand 32-bit int -> floating point conversions. Return true if
successful. */
void
rs6000_expand_convert_si_to_sfdf (rtx dest, rtx src, bool unsigned_p)
{
enum machine_mode dmode = GET_MODE (dest);
rtx (*func_si) (rtx, rtx, rtx, rtx);
rtx (*func_si_mem) (rtx, rtx);
rtx (*func_di) (rtx, rtx);
rtx reg, stack;
gcc_assert (GET_MODE (src) == SImode);
if (dmode == SFmode)
{
if (unsigned_p)
{
gcc_assert (TARGET_FCFIDUS && TARGET_LFIWZX);
func_si = gen_floatunssisf2_lfiwzx;
func_si_mem = gen_floatunssisf2_lfiwzx_mem;
func_di = gen_floatunsdisf2;
}
else
{
gcc_assert (TARGET_FCFIDS && TARGET_LFIWAX);
func_si = gen_floatsisf2_lfiwax;
func_si_mem = gen_floatsisf2_lfiwax_mem;
func_di = gen_floatdisf2;
}
}
else if (dmode == DFmode)
{
if (unsigned_p)
{
gcc_assert (TARGET_FCFIDU && TARGET_LFIWZX);
func_si = gen_floatunssidf2_lfiwzx;
func_si_mem = gen_floatunssidf2_lfiwzx_mem;
func_di = gen_floatunsdidf2;
}
else
{
gcc_assert (TARGET_FCFID && TARGET_LFIWAX);
func_si = gen_floatsidf2_lfiwax;
func_si_mem = gen_floatsidf2_lfiwax_mem;
func_di = gen_floatdidf2;
}
}
else
gcc_unreachable ();
if (MEM_P (src))
{
src = rs6000_address_for_fpconvert (src);
emit_insn (func_si_mem (dest, src));
}
else if (!TARGET_MFPGPR)
{
reg = gen_reg_rtx (DImode);
stack = rs6000_allocate_stack_temp (SImode, false, true);
emit_insn (func_si (dest, src, stack, reg));
}
else
{
if (!REG_P (src))
src = force_reg (SImode, src);
reg = convert_to_mode (DImode, src, unsigned_p);
emit_insn (func_di (dest, reg));
}
}
#include "gt-rs6000.h"

View File

@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010
Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
@ -554,6 +555,25 @@ extern int rs6000_vector_align[];
#define TARGET_E500_DOUBLE 0
#define CHECK_E500_OPTIONS do { } while (0)
/* ISA 2.01 allowed FCFID to be done in 32-bit, previously it was 64-bit only.
Enable 32-bit fcfid's on any of the switches for newer ISA machines or
XILINX. */
#define TARGET_FCFID (TARGET_POWERPC64 \
|| TARGET_POPCNTB /* ISA 2.02 */ \
|| TARGET_CMPB /* ISA 2.05 */ \
|| TARGET_POPCNTD /* ISA 2.06 */ \
|| TARGET_XILINX_FPU)
#define TARGET_FCTIDZ TARGET_FCFID
#define TARGET_STFIWX TARGET_PPC_GFXOPT
#define TARGET_LFIWAX TARGET_CMPB
#define TARGET_LFIWZX TARGET_POPCNTD
#define TARGET_FCFIDS TARGET_POPCNTD
#define TARGET_FCFIDU TARGET_POPCNTD
#define TARGET_FCFIDUS TARGET_POPCNTD
#define TARGET_FCTIDUZ TARGET_POPCNTD
#define TARGET_FCTIWUZ TARGET_POPCNTD
/* E500 processors only support plain "sync", not lwsync. */
#define TARGET_NO_LWSYNC TARGET_E500

View File

@ -105,6 +105,11 @@
(UNSPEC_BPERM 51)
(UNSPEC_COPYSIGN 52)
(UNSPEC_PARITY 53)
(UNSPEC_FCTIW 54)
(UNSPEC_FCTID 55)
(UNSPEC_LFIWAX 56)
(UNSPEC_LFIWZX 57)
(UNSPEC_FCTIWUZ 58)
])
;;
@ -252,13 +257,19 @@
(DI "di")])
(define_mode_attr rreg [(SF "f")
(DF "Ws")
(V4SF "Wf")
(V2DF "Wd")])
(DF "ws")
(V4SF "wf")
(V2DF "wd")])
(define_mode_attr rreg2 [(SF "f")
(DF "d")])
(define_mode_attr SI_CONVERT_FP [(SF "TARGET_FCFIDS")
(DF "TARGET_FCFID")])
(define_mode_attr E500_CONVERT [(SF "!TARGET_FPRS")
(DF "TARGET_E500_DOUBLE")])
(define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
(DF "TARGET_DOUBLE_FLOAT")])
@ -6424,29 +6435,149 @@
;; Conversions to and from floating-point.
(define_expand "fixuns_truncsfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(unsigned_fix:SI (match_operand:SF 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
"")
; We don't define lfiwax/lfiwzx with the normal definition, because we
; don't want to support putting SImode in FPR registers.
(define_insn "lfiwax"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(match_operand:SI 1 "indexed_or_indirect_operand" "Z")]
UNSPEC_LFIWAX))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX"
"lfiwax %0,%y1"
[(set_attr "type" "fpload")])
(define_expand "fix_truncsfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(fix:SI (match_operand:SF 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
"")
(define_insn_and_split "floatsi<mode>2_lfiwax"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>,<rreg2>")
(float:SFDF (match_operand:SI 1 "nonimmediate_operand" "Z,r")))
(clobber (match_operand:SI 2 "indexed_or_indirect_operand" "=Z,Z"))
(clobber (match_operand:DI 3 "gpc_reg_operand" "=d,d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
&& <SI_CONVERT_FP>"
"#"
"MEM_P (operands[1]) || reload_completed"
[(pc)]
"
{
if (MEM_P (operands[1]))
{
operands[1] = rs6000_address_for_fpconvert (operands[1]);
emit_insn (gen_lfiwax (operands[3], operands[1]));
}
else
{
emit_move_insn (operands[2], operands[1]);
emit_insn (gen_lfiwax (operands[3], operands[2]));
}
emit_insn (gen_floatdi<mode>2 (operands[0], operands[3]));
DONE;
}"
[(set_attr "length" "8,12")])
(define_expand "fixuns_truncdfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
"")
(define_insn_and_split "floatsi<mode>2_lfiwax_mem"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(float:SFDF (match_operand:SI 1 "memory_operand" "Z")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
&& <SI_CONVERT_FP>"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_lfiwax (operands[2], operands[1]));
emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "8")])
(define_expand "fixuns_truncdfdi2"
[(set (match_operand:DI 0 "register_operand" "")
(unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_VSX"
"")
(define_insn_and_split "floatsi<mode>2_lfiwax_mem2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(float:SFDF
(sign_extend:DI
(match_operand:SI 1 "memory_operand" "Z"))))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
&& <SI_CONVERT_FP>"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_lfiwax (operands[2], operands[1]));
emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "8")])
(define_insn "lfiwzx"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(match_operand:SI 1 "indexed_or_indirect_operand" "Z")]
UNSPEC_LFIWZX))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX"
"lfiwzx %0,%y1"
[(set_attr "type" "fpload")])
(define_insn_and_split "floatunssi<mode>2_lfiwzx"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>,<rreg2>")
(unsigned_float:SFDF (match_operand:SI 1 "gpc_reg_operand" "Z,r")))
(clobber (match_operand:SI 2 "indexed_or_indirect_operand" "=Z,Z"))
(clobber (match_operand:DI 3 "gpc_reg_operand" "=d,d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
&& <SI_CONVERT_FP>"
"#"
"MEM_P (operands[1]) || reload_completed"
[(pc)]
"
{
if (MEM_P (operands[1]))
{
operands[1] = rs6000_address_for_fpconvert (operands[1]);
emit_insn (gen_lfiwzx (operands[3], operands[1]));
}
else
{
emit_move_insn (operands[2], operands[1]);
emit_insn (gen_lfiwzx (operands[3], operands[2]));
}
emit_insn (gen_floatdi<mode>2 (operands[0], operands[3]));
DONE;
}"
[(set_attr "length" "8,12")])
(define_insn_and_split "floatunssi<mode>2_lfiwzx_mem"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unsigned_float:SFDF (match_operand:SI 1 "memory_operand" "Z")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
&& <SI_CONVERT_FP>"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_lfiwzx (operands[2], operands[1]));
emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "8")])
(define_insn_and_split "floatunssi<mode>2_lfiwzx_mem2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unsigned_float:SFDF
(zero_extend:DI
(match_operand:SI 1 "memory_operand" "Z"))))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
&& <SI_CONVERT_FP>"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_lfiwzx (operands[2], operands[1]));
emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "8")])
; For each of these conversions, there is a define_expand, a define_insn
; with a '#' template, and a define_split (with C code). The idea is
@ -6455,7 +6586,7 @@
(define_expand "floatsidf2"
[(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
(float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
(use (match_dup 2))
(use (match_dup 3))
(clobber (match_dup 4))
@ -6467,19 +6598,31 @@
{
if (TARGET_E500_DOUBLE)
{
if (!REG_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
DONE;
}
if (TARGET_POWERPC64)
else if (TARGET_LFIWAX && TARGET_FCFID)
{
rtx x = convert_to_mode (DImode, operands[1], 0);
emit_insn (gen_floatdidf2 (operands[0], x));
rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], false);
DONE;
}
else if (TARGET_FCFID)
{
rtx dreg = operands[1];
if (!REG_P (dreg))
dreg = force_reg (SImode, dreg);
dreg = convert_to_mode (DImode, dreg, false);
emit_insn (gen_floatdidf2 (operands[0], dreg));
DONE;
}
if (!REG_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, GEN_INT (0x43300000));
operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503601774854144\", DFmode));
operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0);
operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
operands[5] = gen_reg_rtx (DFmode);
operands[6] = gen_reg_rtx (SImode);
}")
@ -6492,7 +6635,7 @@
(clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
(clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))
(clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"! TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"#"
""
[(pc)]
@ -6518,37 +6661,79 @@
}"
[(set_attr "length" "24")])
;; If we don't have a direct conversion to single precision, don't enable this
;; conversion for 32-bit without fast math, because we don't have the insn to
;; generate the fixup swizzle to avoid double rounding problems.
(define_expand "floatunssisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
"")
(unsigned_float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
&& (!TARGET_FPRS
|| (TARGET_FPRS
&& ((TARGET_FCFIDUS && TARGET_LFIWZX)
|| (TARGET_DOUBLE_FLOAT && TARGET_FCFID
&& (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
"
{
if (!TARGET_FPRS)
{
if (!REG_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
}
else if (TARGET_LFIWZX && TARGET_FCFIDUS)
{
rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], true);
DONE;
}
else
{
rtx dreg = operands[1];
if (!REG_P (dreg))
dreg = force_reg (SImode, dreg);
dreg = convert_to_mode (DImode, dreg, true);
emit_insn (gen_floatdisf2 (operands[0], dreg));
DONE;
}
}")
(define_expand "floatunssidf2"
[(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
(unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
(unsigned_float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
(use (match_dup 2))
(use (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])]
"TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
"TARGET_HARD_FLOAT
&& ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
"
{
if (TARGET_E500_DOUBLE)
{
if (!REG_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
emit_insn (gen_spe_floatunssidf2 (operands[0], operands[1]));
DONE;
}
if (TARGET_POWERPC64)
else if (TARGET_LFIWZX && TARGET_FCFID)
{
rtx x = convert_to_mode (DImode, operands[1], 1);
emit_insn (gen_floatdidf2 (operands[0], x));
rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], true);
DONE;
}
else if (TARGET_FCFID)
{
rtx dreg = operands[1];
if (!REG_P (dreg))
dreg = force_reg (SImode, dreg);
dreg = convert_to_mode (DImode, dreg, true);
emit_insn (gen_floatdidf2 (operands[0], dreg));
DONE;
}
if (!REG_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
operands[2] = force_reg (SImode, GEN_INT (0x43300000));
operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode));
operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0);
operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
operands[5] = gen_reg_rtx (DFmode);
}")
@ -6559,7 +6744,8 @@
(use (match_operand:DF 3 "gpc_reg_operand" "d"))
(clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
(clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"! TARGET_FCFIDU && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& !(TARGET_FCFID && TARGET_POWERPC64)"
"#"
""
[(pc)]
@ -6583,46 +6769,85 @@
}"
[(set_attr "length" "20")])
(define_expand "fix_truncdfsi2"
[(parallel [(set (match_operand:SI 0 "fix_trunc_dest_operand" "")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
"(TARGET_POWER2 || TARGET_POWERPC)
&& TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
(define_expand "fix_trunc<mode>si2"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT
&& ((TARGET_FPRS && <TARGET_FLOAT>) || <E500_CONVERT>)"
"
{
if (TARGET_E500_DOUBLE)
if (!<E500_CONVERT>)
{
emit_insn (gen_spe_fix_truncdfsi2 (operands[0], operands[1]));
DONE;
}
operands[2] = gen_reg_rtx (DImode);
if (TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
&& gpc_reg_operand(operands[0], GET_MODE (operands[0])))
{
operands[3] = gen_reg_rtx (DImode);
emit_insn (gen_fix_truncdfsi2_mfpgpr (operands[0], operands[1],
operands[2], operands[3]));
rtx tmp, stack;
if (TARGET_STFIWX)
{
tmp = gen_reg_rtx (DImode);
stack = rs6000_allocate_stack_temp (SImode, false, true);
emit_insn (gen_fix_trunc<mode>si2_stfiwx (operands[0], operands[1],
tmp, stack));
}
else
{
tmp = gen_reg_rtx (DImode);
stack = rs6000_allocate_stack_temp (DImode, true, false);
emit_insn (gen_fix_trunc<mode>si2_internal (operands[0], operands[1],
tmp, stack));
}
DONE;
}
if (TARGET_PPC_GFXOPT)
{
rtx orig_dest = operands[0];
if (! memory_operand (orig_dest, GET_MODE (orig_dest)))
operands[0] = assign_stack_temp (SImode, GET_MODE_SIZE (SImode), 0);
emit_insn (gen_fix_truncdfsi2_internal_gfxopt (operands[0], operands[1],
operands[2]));
if (operands[0] != orig_dest)
emit_move_insn (orig_dest, operands[0]);
DONE;
}
operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
}")
(define_insn_and_split "*fix_truncdfsi2_internal"
(define_insn_and_split "fix_trunc<mode>si2_stfiwx"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
(clobber (match_operand:SI 3 "indexed_or_indirect_operand" "=Z"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
&& TARGET_STFIWX"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
if (TARGET_MFPGPR && TARGET_POWERPC64 && REG_P (operands[0])
&& INT_REGNO_P (REGNO (operands[0])))
{
rtx reg = gen_lowpart (DImode, operands[0]);
emit_move_insn (reg, operands[2]);
}
else
{
emit_insn (gen_stfiwx (operands[3], operands[2]));
emit_move_insn (operands[0], operands[3]);
}
DONE;
}"
[(set_attr "length" "12")])
(define_insn_and_split "*fix_trunc<mode>si2_mem"
[(set (match_operand:SI 0 "memory_operand" "=Z")
(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
&& TARGET_STFIWX"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
emit_insn (gen_stfiwx (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "8")])
(define_insn_and_split "fix_trunc<mode>si2_internal"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg>")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
(clobber (match_operand:DI 3 "offsettable_mem_operand" "=o"))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
@ -6636,143 +6861,194 @@
gcc_assert (MEM_P (operands[3]));
lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
emit_insn (gen_fctiwz (operands[2], operands[1]));
emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
emit_move_insn (operands[3], operands[2]);
emit_move_insn (operands[0], lowword);
DONE;
}"
[(set_attr "length" "16")])
(define_insn_and_split "fix_truncdfsi2_internal_gfxopt"
[(set (match_operand:SI 0 "memory_operand" "=Z")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
&& TARGET_DOUBLE_FLOAT
&& TARGET_PPC_GFXOPT"
(define_expand "fix_trunc<mode>di2"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
&& TARGET_FCFID"
"")
(define_insn "*fix_trunc<mode>di2_fctidz"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
&& TARGET_FCFID && !VECTOR_UNIT_VSX_P (<MODE>mode)"
"fctidz %0,%1"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunc<mode>si2"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT
&& ((TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ && TARGET_STFIWX)
|| <E500_CONVERT>)"
"
{
if (!<E500_CONVERT>)
{
rtx tmp = gen_reg_rtx (DImode);
rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1],
tmp, stack));
DONE;
}
}")
(define_insn_and_split "fixuns_trunc<mode>si2_stfiwx"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(unsigned_fix:SI
(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
(clobber (match_operand:SI 3 "indexed_or_indirect_operand" "=Z"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
&& TARGET_STFIWX"
"#"
"&& 1"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_fctiwz (operands[2], operands[1]));
emit_insn (gen_fctiwuz_<mode> (operands[2], operands[1]));
if (TARGET_MFPGPR && TARGET_POWERPC64 && REG_P (operands[0])
&& INT_REGNO_P (REGNO (operands[0])))
{
rtx reg = gen_lowpart (DImode, operands[0]);
emit_move_insn (reg, operands[2]);
}
else
{
emit_insn (gen_stfiwx (operands[3], operands[2]));
emit_move_insn (operands[0], operands[3]);
}
DONE;
}"
[(set_attr "length" "12")])
(define_insn_and_split "*fixuns_trunc<mode>si2_mem"
[(set (match_operand:SI 0 "memory_operand" "=Z")
(unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
&& TARGET_STFIWX"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_insn (gen_fctiwuz_<mode> (operands[2], operands[1]));
emit_insn (gen_stfiwx (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "16")])
[(set_attr "length" "8")])
(define_insn_and_split "fix_truncdfsi2_mfpgpr"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
(clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))]
"TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
&& TARGET_DOUBLE_FLOAT"
"#"
"&& 1"
[(set (match_dup 2) (unspec:DI [(fix:SI (match_dup 1))] UNSPEC_FCTIWZ))
(set (match_dup 3) (match_dup 2))
(set (match_dup 0) (subreg:SI (match_dup 3) 4))]
""
[(set_attr "length" "12")])
(define_expand "fixuns_trunc<mode>di2"
[(set (match_operand:DI 0 "register_operand" "")
(unsigned_fix:DI (match_operand:SFDF 1 "register_operand" "")))]
"TARGET_HARD_FLOAT && (TARGET_FCTIDUZ || VECTOR_UNIT_VSX_P (<MODE>mode))"
"")
(define_insn "*fixuns_trunc<mode>di2_fctiduz"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
&& TARGET_FCTIDUZ && !VECTOR_UNIT_VSX_P (<MODE>mode)"
"fctiduz %0,%1"
[(set_attr "type" "fp")])
; 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"
(define_insn "fctiwz_<mode>"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))]
(unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))]
UNSPEC_FCTIWZ))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
&& TARGET_DOUBLE_FLOAT"
"{fcirz|fctiwz} %0,%1"
[(set_attr "type" "fp")])
(define_expand "btruncdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIZ))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
(define_insn "fctiwuz_<mode>"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(unsigned_fix:SI
(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>"))]
UNSPEC_FCTIWUZ))]
"TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ"
"fctiwuz %0,%1"
[(set_attr "type" "fp")])
;; No VSX equivalent to fctid
(define_insn "lrint<mode>di2"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FCTID))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"fctid %0,%1"
[(set_attr "type" "fp")])
(define_expand "btrunc<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
UNSPEC_FRIZ))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"")
(define_insn "*btruncdf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& !VECTOR_UNIT_VSX_P (DFmode)"
(define_insn "*btrunc<mode>2_fpr"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FRIZ))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
&& !VECTOR_UNIT_VSX_P (<MODE>mode)"
"friz %0,%1"
[(set_attr "type" "fp")])
(define_insn "btruncsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
"friz %0,%1"
[(set_attr "type" "fp")])
(define_expand "ceildf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIP))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
(define_expand "ceil<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
UNSPEC_FRIP))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"")
(define_insn "*ceildf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIP))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& !VECTOR_UNIT_VSX_P (DFmode)"
(define_insn "*ceil<mode>2_fpr"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FRIP))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
&& !VECTOR_UNIT_VSX_P (<MODE>mode)"
"frip %0,%1"
[(set_attr "type" "fp")])
(define_insn "ceilsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
"frip %0,%1"
[(set_attr "type" "fp")])
(define_expand "floordf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIM))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
(define_expand "floor<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
UNSPEC_FRIM))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"")
(define_insn "*floordf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIM))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& !VECTOR_UNIT_VSX_P (DFmode)"
"frim %0,%1"
[(set_attr "type" "fp")])
(define_insn "floorsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
(define_insn "*floor<mode>2_fpr"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FRIM))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
&& !VECTOR_UNIT_VSX_P (<MODE>mode)"
"frim %0,%1"
[(set_attr "type" "fp")])
;; No VSX equivalent to frin
(define_insn "rounddf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIN))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
(define_insn "round<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FRIN))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
"frin %0,%1"
[(set_attr "type" "fp")])
(define_insn "roundsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
"frin %0,%1"
[(set_attr "type" "fp")])
(define_expand "ftruncdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(fix:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
"VECTOR_UNIT_VSX_P (DFmode)"
"")
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
[(set (match_operand:SI 0 "memory_operand" "=Z")
@ -6782,76 +7058,154 @@
"stfiwx %1,%y0"
[(set_attr "type" "fpstore")])
;; If we don't have a direct conversion to single precision, don't enable this
;; conversion for 32-bit without fast math, because we don't have the insn to
;; generate the fixup swizzle to avoid double rounding problems.
(define_expand "floatsisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT && !TARGET_FPRS"
"")
(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
&& (!TARGET_FPRS
|| (TARGET_FPRS
&& ((TARGET_FCFIDS && TARGET_LFIWAX)
|| (TARGET_DOUBLE_FLOAT && TARGET_FCFID
&& (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
"
{
if (!TARGET_FPRS)
{
if (!REG_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
}
else if (TARGET_FCFIDS && TARGET_LFIWAX)
{
rs6000_expand_convert_si_to_sfdf (operands[0], operands[1], false);
DONE;
}
else
{
rtx dreg = operands[1];
if (!REG_P (dreg))
dreg = force_reg (SImode, dreg);
dreg = convert_to_mode (DImode, dreg, false);
emit_insn (gen_floatdisf2 (operands[0], dreg));
DONE;
}
}")
(define_expand "floatdidf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
"(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
&& TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
"TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
"")
(define_insn "*floatdidf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))]
"(TARGET_POWERPC64 || TARGET_XILINX_FPU)
&& TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
(float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
"TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
&& !VECTOR_UNIT_VSX_P (DFmode)"
"fcfid %0,%1"
[(set_attr "type" "fp")])
; Allow the combiner to merge source memory operands to the conversion so that
; the optimizer/register allocator doesn't try to load the value too early in a
; GPR and then use store/load to move it to a FPR and suffer from a store-load
; hit. We will split after reload to avoid the trip through the GPRs
(define_insn_and_split "*floatdidf2_mem"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(float:DF (match_operand:DI 1 "memory_operand" "m")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS && TARGET_FCFID"
"#"
"&& reload_completed"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (float:DF (match_dup 2)))]
""
[(set_attr "length" "8")])
(define_expand "floatunsdidf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
"TARGET_VSX"
(unsigned_float:DF
(match_operand:DI 1 "gpc_reg_operand" "")))]
"TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode)"
"")
(define_expand "fix_truncdfdi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(fix:DI (match_operand:DF 1 "gpc_reg_operand" "")))]
"(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
&& TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
"")
(define_insn "*floatunsdidf2_fcfidu"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "d")))]
"TARGET_FCFIDU && !VECTOR_UNIT_VSX_P (DFmode)"
"fcfidu %0,%1"
[(set_attr "type" "fp")
(set_attr "length" "4")])
(define_insn "*fix_truncdfdi2_fpr"
[(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
(fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
"(TARGET_POWERPC64 || TARGET_XILINX_FPU)
&& TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
&& !VECTOR_UNIT_VSX_P (DFmode)"
"fctidz %0,%1"
[(set_attr "type" "fp")])
(define_insn_and_split "*floatunsdidf2_mem"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unsigned_float:DF (match_operand:DI 1 "memory_operand" "m")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode)"
"#"
"&& reload_completed"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (unsigned_float:DF (match_dup 2)))]
""
[(set_attr "length" "8")])
(define_expand "floatdisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
"TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
&& (TARGET_FCFIDS || TARGET_POWERPC64 || flag_unsafe_math_optimizations)"
"
{
rtx val = operands[1];
if (!flag_unsafe_math_optimizations)
if (!TARGET_FCFIDS)
{
rtx label = gen_label_rtx ();
val = gen_reg_rtx (DImode);
emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
emit_label (label);
rtx val = operands[1];
if (!flag_unsafe_math_optimizations)
{
rtx label = gen_label_rtx ();
val = gen_reg_rtx (DImode);
emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
emit_label (label);
}
emit_insn (gen_floatdisf2_internal1 (operands[0], val));
DONE;
}
emit_insn (gen_floatdisf2_internal1 (operands[0], val));
DONE;
}")
(define_insn "floatdisf2_fcfids"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
&& TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
"fcfids %0,%1"
[(set_attr "type" "fp")])
(define_insn_and_split "*floatdisf2_mem"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(float:SF (match_operand:DI 1 "memory_operand" "m")))
(clobber (match_scratch:DI 2 "=f"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
&& TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_move_insn (operands[2], operands[1]);
emit_insn (gen_floatdisf2_fcfids (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "8")])
;; This is not IEEE compliant if rounding mode is "round to nearest".
;; If the DI->DF conversion is inexact, then it's possible to suffer
;; from double rounding.
(define_insn_and_split "floatdisf2_internal1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(float:SF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))
(float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))
(clobber (match_scratch:DF 2 "=d"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
"TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
"#"
"&& reload_completed"
[(set (match_dup 2)
@ -6891,6 +7245,38 @@
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (CCUNSmode);
}")
(define_expand "floatunsdisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
&& TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
"")
(define_insn "floatunsdisf2_fcfidus"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
&& TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
"fcfidus %0,%1"
[(set_attr "type" "fp")])
(define_insn_and_split "*floatunsdisf2_mem"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unsigned_float:SF (match_operand:DI 1 "memory_operand" "m")))
(clobber (match_scratch:DI 2 "=f"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
&& TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
"#"
"&& reload_completed"
[(pc)]
"
{
emit_move_insn (operands[2], operands[1]);
emit_insn (gen_floatunsdisf2_fcfidus (operands[0], operands[2]));
DONE;
}"
[(set_attr "length" "8")])
;; Define the DImode operations that can be done in a small number
;; of instructions. The & constraints are to prevent the register
@ -9540,7 +9926,7 @@
gcc_assert (MEM_P (operands[5]));
lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
emit_insn (gen_fctiwz (operands[4], operands[2]));
emit_insn (gen_fctiwz_df (operands[4], operands[2]));
emit_move_insn (operands[5], operands[4]);
emit_move_insn (operands[0], lowword);
DONE;

View File

@ -1,5 +1,5 @@
;; VSX patterns.
;; Copyright (C) 2009
;; Copyright (C) 2009, 2010
;; Free Software Foundation, Inc.
;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com>
@ -73,11 +73,11 @@
;; Map the register class used for float<->int conversions
(define_mode_attr VSr2 [(V2DF "wd")
(V4SF "wf")
(DF "!f#r")])
(DF "ws")])
(define_mode_attr VSr3 [(V2DF "wa")
(V4SF "wa")
(DF "!f#r")])
(DF "ws")])
;; Map the register class for sp<->dp float conversions, destination
(define_mode_attr VSr4 [(SF "ws")

View File

@ -1,3 +1,17 @@
2010-08-23 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/ppc-fpconv-1.c: New test for integer to
floating point conversion code generation.
* gcc.target/powerpc/ppc-fpconv-2.c: Ditto.
* gcc.target/powerpc/ppc-fpconv-3.c: Ditto.
* gcc.target/powerpc/ppc-fpconv-4.c: Ditto.
* gcc.target/powerpc/ppc-fpconv-5.c: New test for floating point
to integer conversion code generation.
* gcc.target/powerpc/ppc-fpconv-6.c: Ditto.
* gcc.target/powerpc/ppc-fpconv-7.c: Ditto.
* gcc.target/powerpc/ppc-fpconv-8.c: Ditto.
* gcc.target/powerpc/ppc-fpconv-9.c: Ditto.
2010-08-27 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/32049

View File

@ -0,0 +1,50 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O2 -mcpu=power7 -ffast-math" } */
/* { dg-final { scan-assembler-times "lfiwax" 2 } } */
/* { dg-final { scan-assembler-times "lfiwzx" 2 } } */
/* { dg-final { scan-assembler-times "fcfids" 3 } } */
/* { dg-final { scan-assembler-times "fcfidus" 1 } } */
/* { dg-final { scan-assembler-times "xscvsxddp" 3 } } */
/* { dg-final { scan-assembler-times "xscvuxddp" 1 } } */
void int_to_float (float *dest, int *src)
{
*dest = (float) *src;
}
void int_to_double (double *dest, int *src)
{
*dest = (double) *src;
}
void uint_to_float (float *dest, unsigned int *src)
{
*dest = (float) *src;
}
void uint_to_double (double *dest, unsigned int *src)
{
*dest = (double) *src;
}
void llong_to_float (float *dest, long long *src)
{
*dest = (float) *src;
}
void llong_to_double (double *dest, long long *src)
{
*dest = (double) *src;
}
void ullong_to_float (float *dest, unsigned long long *src)
{
*dest = (float) *src;
}
void ullong_to_double (double *dest, unsigned long long *src)
{
*dest = (double) *src;
}

View File

@ -0,0 +1,51 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O2 -mcpu=power6 -ffast-math" } */
/* { dg-final { scan-assembler-times "lfiwax" 1 } } */
/* { dg-final { scan-assembler-not "lfiwzx" } } */
/* { dg-final { scan-assembler-times "fcfid " 10 } } */
/* { dg-final { scan-assembler-not "fcfids" } } */
/* { dg-final { scan-assembler-not "fcfidus" } } */
/* { dg-final { scan-assembler-not "xscvsxddp" } } */
/* { dg-final { scan-assembler-not "xscvuxddp" } } */
void int_to_float (float *dest, int *src)
{
*dest = (float) *src;
}
void int_to_double (double *dest, int *src)
{
*dest = (double) *src;
}
void uint_to_float (float *dest, unsigned int *src)
{
*dest = (float) *src;
}
void uint_to_double (double *dest, unsigned int *src)
{
*dest = (double) *src;
}
void llong_to_float (float *dest, long long *src)
{
*dest = (float) *src;
}
void llong_to_double (double *dest, long long *src)
{
*dest = (double) *src;
}
void ullong_to_float (float *dest, unsigned long long *src)
{
*dest = (float) *src;
}
void ullong_to_double (double *dest, unsigned long long *src)
{
*dest = (double) *src;
}

View File

@ -0,0 +1,51 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O2 -mcpu=power5 -ffast-math" } */
/* { dg-final { scan-assembler-not "lfiwax" } } */
/* { dg-final { scan-assembler-not "lfiwzx" } } */
/* { dg-final { scan-assembler-times "fcfid " 10 } } */
/* { dg-final { scan-assembler-not "fcfids" } } */
/* { dg-final { scan-assembler-not "fcfidus" } } */
/* { dg-final { scan-assembler-not "xscvsxddp" } } */
/* { dg-final { scan-assembler-not "xscvuxddp" } } */
void int_to_float (float *dest, int *src)
{
*dest = (float) *src;
}
void int_to_double (double *dest, int *src)
{
*dest = (double) *src;
}
void uint_to_float (float *dest, unsigned int *src)
{
*dest = (float) *src;
}
void uint_to_double (double *dest, unsigned int *src)
{
*dest = (double) *src;
}
void llong_to_float (float *dest, long long *src)
{
*dest = (float) *src;
}
void llong_to_double (double *dest, long long *src)
{
*dest = (double) *src;
}
void ullong_to_float (float *dest, unsigned long long *src)
{
*dest = (float) *src;
}
void ullong_to_double (double *dest, unsigned long long *src)
{
*dest = (double) *src;
}

View File

@ -0,0 +1,51 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O2 -mcpu=750 -ffast-math" } */
/* { dg-final { scan-assembler-not "lfiwax" } } */
/* { dg-final { scan-assembler-not "lfiwzx" } } */
/* { dg-final { scan-assembler-not "fcfid " } } */
/* { dg-final { scan-assembler-not "fcfids" } } */
/* { dg-final { scan-assembler-not "fcfidus" } } */
/* { dg-final { scan-assembler-not "xscvsxddp" } } */
/* { dg-final { scan-assembler-not "xscvuxddp" } } */
void int_to_float (float *dest, int *src)
{
*dest = (float) *src;
}
void int_to_double (double *dest, int *src)
{
*dest = (double) *src;
}
void uint_to_float (float *dest, unsigned int *src)
{
*dest = (float) *src;
}
void uint_to_double (double *dest, unsigned int *src)
{
*dest = (double) *src;
}
void llong_to_float (float *dest, long long *src)
{
*dest = (float) *src;
}
void llong_to_double (double *dest, long long *src)
{
*dest = (double) *src;
}
void ullong_to_float (float *dest, unsigned long long *src)
{
*dest = (float) *src;
}
void ullong_to_double (double *dest, unsigned long long *src)
{
*dest = (double) *src;
}

View File

@ -0,0 +1,22 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O3 -mcpu=power7 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 2 } } */
/* { dg-final { scan-assembler-times "fctiwuz" 2 } } */
/* { dg-final { scan-assembler-times "fctidz" 1 } } */
/* { dg-final { scan-assembler-times "fctiduz" 1 } } */
/* { dg-final { scan-assembler-times "xscvdpsxds" 1 } } */
/* { dg-final { scan-assembler-times "xscvdpuxds" 1 } } */
void float_to_int (int *dest, float src) { *dest = (int) src; }
void double_to_int (int *dest, double src) { *dest = (int) src; }
void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; }
void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; }
void float_to_llong (long long *dest, float src) { *dest = (long long) src; }
void double_to_llong (long long *dest, double src) { *dest = (long long) src; }
void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; }
void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; }

View File

@ -0,0 +1,22 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O3 -mcpu=power6 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 2 } } */
/* { dg-final { scan-assembler-not "fctiwuz" } } */
/* { dg-final { scan-assembler-times "fctidz" 8 } } */
/* { dg-final { scan-assembler-not "fctiduz" } } */
/* { dg-final { scan-assembler-not "xscvdpsxds" } } */
/* { dg-final { scan-assembler-not "xscvdpuxds" } } */
void float_to_int (int *dest, float src) { *dest = (int) src; }
void double_to_int (int *dest, double src) { *dest = (int) src; }
void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; }
void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; }
void float_to_llong (long long *dest, float src) { *dest = (long long) src; }
void double_to_llong (long long *dest, double src) { *dest = (long long) src; }
void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; }
void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; }

View File

@ -0,0 +1,22 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O3 -mcpu=power5 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 2 } } */
/* { dg-final { scan-assembler-not "fctiwuz" } } */
/* { dg-final { scan-assembler-times "fctidz" 8 } } */
/* { dg-final { scan-assembler-not "fctiduz" } } */
/* { dg-final { scan-assembler-not "xscvdpsxds" } } */
/* { dg-final { scan-assembler-not "xscvdpuxds" } } */
void float_to_int (int *dest, float src) { *dest = (int) src; }
void double_to_int (int *dest, double src) { *dest = (int) src; }
void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; }
void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; }
void float_to_llong (long long *dest, float src) { *dest = (long long) src; }
void double_to_llong (long long *dest, double src) { *dest = (long long) src; }
void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; }
void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; }

View File

@ -0,0 +1,22 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O3 -mcpu=750 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 6 } } */
/* { dg-final { scan-assembler-not "fctiwuz" } } */
/* { dg-final { scan-assembler-not "fctidz" } } */
/* { dg-final { scan-assembler-not "fctiduz" } } */
/* { dg-final { scan-assembler-not "xscvdpsxds" } } */
/* { dg-final { scan-assembler-not "xscvdpuxds" } } */
void float_to_int (int *dest, float src) { *dest = (int) src; }
void double_to_int (int *dest, double src) { *dest = (int) src; }
void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; }
void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; }
void float_to_llong (long long *dest, float src) { *dest = (long long) src; }
void double_to_llong (long long *dest, double src) { *dest = (long long) src; }
void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; }
void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; }

View File

@ -0,0 +1,11 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O3 -mcpu=power7 -ffast-math" } */
/* { dg-final { scan-assembler-not "lwz" } } */
/* { dg-final { scan-assembler-not "stw" } } */
/* { dg-final { scan-assembler-not "ld " } } */
/* { dg-final { scan-assembler-not "std" } } */
void float_to_llong (long long *dest, float src) { *dest = (long long) src; }
void double_to_llong (long long *dest, double src) { *dest = (long long) src; }