Commit 19be72ab by Michael Meissner Committed by Michael Meissner

vector.md (GPR move splitter): Do not split moves of vectors in GPRS if they are…

vector.md (GPR move splitter): Do not split moves of vectors in GPRS if they are direct moves or quad word...

[gcc]
2013-06-10  Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Pat Haugen <pthaugen@us.ibm.com>
	    Peter Bergner <bergner@vnet.ibm.com>

	* config/rs6000/vector.md (GPR move splitter): Do not split moves
	of vectors in GPRS if they are direct moves or quad word load or
	store moves.

	* config/rs6000/rs6000-protos.h (rs6000_output_move_128bit): Add
	declaration.
	(direct_move_p): Likewise.
	(quad_load_store_p): Likewise.

	* config/rs6000/rs6000.c (enum rs6000_reg_type): Simplify register
	classes into bins based on the physical register type.
	(reg_class_to_reg_type): Likewise.
	(IS_STD_REG_TYPE): Likewise.
	(IS_FP_VECT_REG_TYPE): Likewise.
	(reload_fpr_gpr): Arrays to determine what insn to use if we can
	use direct move instructions.
	(reload_gpr_vsx): Likewise.
	(reload_vsx_gpr): Likewise.
	(rs6000_init_hard_regno_mode_ok): Precalculate the register type
	information that is a simplification of register classes.  Also
	precalculate direct move reload helpers.
	(direct_move_p): New function to return true if the operation can
	be done as a direct move instruciton.
	(quad_load_store_p): New function to return true if the operation
	is a quad memory operation.
	(rs6000_legitimize_address): If quad memory, only allow register
	indirect for TImode addresses.
	(rs6000_legitimate_address_p): Likewise.
	(enum reload_reg_type): Delete, replace with rs6000_reg_type.
	(rs6000_reload_register_type): Likewise.
	(register_to_reg_type): Return register type.
	(rs6000_secondary_reload_simple_move): New helper function for
	secondary reload and secondary memory needed to identify anything
	that is a simple move, and does not need reloading.
	(rs6000_secondary_reload_direct_move): New helper function for
	secondary reload to identify cases that can be done with several
	instructions via the direct move instructions.
	(rs6000_secondary_reload_move): New helper function for secondary
	reload to identify moves between register types that can be done.
	(rs6000_secondary_reload): Add support for quad memory operations
	and for direct move.
	(rs6000_secondary_memory_needed): Likewise.
	(rs6000_debug_secondary_memory_needed): Change argument names.
	(rs6000_output_move_128bit): New function to return the move to
	use for 128-bit moves, including knowing about the various
	limitations of quad memory operations.

	* config/rs6000/vsx.md (vsx_mov<mode>): Add support for quad
	memory operations.  call rs6000_output_move_128bit for the actual
	instruciton(s) to generate.
	(vsx_movti_64bit): Likewise.

	* config/rs6000/rs6000.md (UNSPEC_P8V_FMRGOW): New unspec values.
	(UNSPEC_P8V_MTVSRWZ): Likewise.
	(UNSPEC_P8V_RELOAD_FROM_GPR): Likewise.
	(UNSPEC_P8V_MTVSRD): Likewise.
	(UNSPEC_P8V_XXPERMDI): Likewise.
	(UNSPEC_P8V_RELOAD_FROM_VSX): Likewise.
	(UNSPEC_FUSION_GPR): Likewise.
	(FMOVE128_GPR): New iterator for direct move.
	(f32_lv): New mode attribute for load/store of SFmode/SDmode
	values.
	(f32_sv): Likewise.
	(f32_dm): Likewise.
	(zero_extend<mode>di2_internal1): Add support for power8 32-bit
	loads and direct move instructions.
	(zero_extendsidi2_lfiwzx): Likewise.
	(extendsidi2_lfiwax): Likewise.
	(extendsidi2_nocell): Likewise.
	(floatsi<mode>2_lfiwax): Likewise.
	(lfiwax): Likewise.
	(floatunssi<mode>2_lfiwzx): Likewise.
	(lfiwzx): Likewise.
	(fix_trunc<mode>_stfiwx): Likewise.
	(fixuns_trunc<mode>_stfiwx): Likewise.
	(mov<mode>_hardfloat, 32-bit floating point): Likewise.
	(mov<move>_hardfloat64, 64-bit floating point): Likewise.
	(parity<mode>2_cmpb): Set length/type attr.
	(unnamed shift right patterns, mov<mode>_internal2): Change type attr
	for 'mr.' to fast_compare.
	(bpermd_<mode>): Change type attr to popcnt.
	(p8_fmrgow_<mode>): New insns for power8 direct move support.
	(p8_mtvsrwz_1): Likewise.
	(p8_mtvsrwz_2): Likewise.
	(reload_fpr_from_gpr<mode>): Likewise.
	(p8_mtvsrd_1): Likewise.
	(p8_mtvsrd_2): Likewise.
	(p8_xxpermdi_<mode>): Likewise.
	(reload_vsx_from_gpr<mode>): Likewise.
	(reload_vsx_from_gprsf): Likewise.
	(p8_mfvsrd_3_<mode>): LIkewise.
	(reload_gpr_from_vsx<mode>): Likewise.
	(reload_gpr_from_vsxsf): Likewise.
	(p8_mfvsrd_4_disf): Likewise.
	(multi-word GPR splits): Do not split direct moves or quad memory
	operations.

[gcc/testsuite]
2013-06-10  Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Pat Haugen <pthaugen@us.ibm.com>
	    Peter Bergner <bergner@vnet.ibm.com>

	* gcc.target/powerpc/direct-move-vint1.c: New tests for power8
	direct move instructions.
	* gcc.target/powerpc/direct-move-vint2.c: Likewise.
	* gcc.target/powerpc/direct-move.h: Likewise.
	* gcc.target/powerpc/direct-move-float1.c: Likewise.
	* gcc.target/powerpc/direct-move-float2.c: Likewise.
	* gcc.target/powerpc/direct-move-double1.c: Likewise.
	* gcc.target/powerpc/direct-move-double2.c: Likewise.
	* gcc.target/powerpc/direct-move-long1.c: Likewise.
	* gcc.target/powerpc/direct-move-long2.c: Likewise.


Co-Authored-By: Pat Haugen <pthaugen@us.ibm.com>
Co-Authored-By: Peter Bergner <bergner@vnet.ibm.com>

From-SVN: r199918
parent 16876bdc
2013-06-10 Michael Meissner <meissner@linux.vnet.ibm.com>
Pat Haugen <pthaugen@us.ibm.com>
Peter Bergner <bergner@vnet.ibm.com>
* config/rs6000/vector.md (GPR move splitter): Do not split moves
of vectors in GPRS if they are direct moves or quad word load or
store moves.
* config/rs6000/rs6000-protos.h (rs6000_output_move_128bit): Add
declaration.
(direct_move_p): Likewise.
(quad_load_store_p): Likewise.
* config/rs6000/rs6000.c (enum rs6000_reg_type): Simplify register
classes into bins based on the physical register type.
(reg_class_to_reg_type): Likewise.
(IS_STD_REG_TYPE): Likewise.
(IS_FP_VECT_REG_TYPE): Likewise.
(reload_fpr_gpr): Arrays to determine what insn to use if we can
use direct move instructions.
(reload_gpr_vsx): Likewise.
(reload_vsx_gpr): Likewise.
(rs6000_init_hard_regno_mode_ok): Precalculate the register type
information that is a simplification of register classes. Also
precalculate direct move reload helpers.
(direct_move_p): New function to return true if the operation can
be done as a direct move instruciton.
(quad_load_store_p): New function to return true if the operation
is a quad memory operation.
(rs6000_legitimize_address): If quad memory, only allow register
indirect for TImode addresses.
(rs6000_legitimate_address_p): Likewise.
(enum reload_reg_type): Delete, replace with rs6000_reg_type.
(rs6000_reload_register_type): Likewise.
(register_to_reg_type): Return register type.
(rs6000_secondary_reload_simple_move): New helper function for
secondary reload and secondary memory needed to identify anything
that is a simple move, and does not need reloading.
(rs6000_secondary_reload_direct_move): New helper function for
secondary reload to identify cases that can be done with several
instructions via the direct move instructions.
(rs6000_secondary_reload_move): New helper function for secondary
reload to identify moves between register types that can be done.
(rs6000_secondary_reload): Add support for quad memory operations
and for direct move.
(rs6000_secondary_memory_needed): Likewise.
(rs6000_debug_secondary_memory_needed): Change argument names.
(rs6000_output_move_128bit): New function to return the move to
use for 128-bit moves, including knowing about the various
limitations of quad memory operations.
* config/rs6000/vsx.md (vsx_mov<mode>): Add support for quad
memory operations. call rs6000_output_move_128bit for the actual
instruciton(s) to generate.
(vsx_movti_64bit): Likewise.
* config/rs6000/rs6000.md (UNSPEC_P8V_FMRGOW): New unspec values.
(UNSPEC_P8V_MTVSRWZ): Likewise.
(UNSPEC_P8V_RELOAD_FROM_GPR): Likewise.
(UNSPEC_P8V_MTVSRD): Likewise.
(UNSPEC_P8V_XXPERMDI): Likewise.
(UNSPEC_P8V_RELOAD_FROM_VSX): Likewise.
(UNSPEC_FUSION_GPR): Likewise.
(FMOVE128_GPR): New iterator for direct move.
(f32_lv): New mode attribute for load/store of SFmode/SDmode
values.
(f32_sv): Likewise.
(f32_dm): Likewise.
(zero_extend<mode>di2_internal1): Add support for power8 32-bit
loads and direct move instructions.
(zero_extendsidi2_lfiwzx): Likewise.
(extendsidi2_lfiwax): Likewise.
(extendsidi2_nocell): Likewise.
(floatsi<mode>2_lfiwax): Likewise.
(lfiwax): Likewise.
(floatunssi<mode>2_lfiwzx): Likewise.
(lfiwzx): Likewise.
(fix_trunc<mode>_stfiwx): Likewise.
(fixuns_trunc<mode>_stfiwx): Likewise.
(mov<mode>_hardfloat, 32-bit floating point): Likewise.
(mov<move>_hardfloat64, 64-bit floating point): Likewise.
(parity<mode>2_cmpb): Set length/type attr.
(unnamed shift right patterns, mov<mode>_internal2): Change type attr
for 'mr.' to fast_compare.
(bpermd_<mode>): Change type attr to popcnt.
(p8_fmrgow_<mode>): New insns for power8 direct move support.
(p8_mtvsrwz_1): Likewise.
(p8_mtvsrwz_2): Likewise.
(reload_fpr_from_gpr<mode>): Likewise.
(p8_mtvsrd_1): Likewise.
(p8_mtvsrd_2): Likewise.
(p8_xxpermdi_<mode>): Likewise.
(reload_vsx_from_gpr<mode>): Likewise.
(reload_vsx_from_gprsf): Likewise.
(p8_mfvsrd_3_<mode>): LIkewise.
(reload_gpr_from_vsx<mode>): Likewise.
(reload_gpr_from_vsxsf): Likewise.
(p8_mfvsrd_4_disf): Likewise.
(multi-word GPR splits): Do not split direct moves or quad memory
operations.
2013-06-10 David Malcolm <dmalcolm@redhat.com>
* tree-into-ssa.c (interesting_blocks): Make static.
......
......@@ -50,6 +50,7 @@ extern rtx rs6000_got_register (rtx);
extern rtx find_addr_reg (rtx);
extern rtx gen_easy_altivec_constant (rtx);
extern const char *output_vec_const_move (rtx *);
extern const char *rs6000_output_move_128bit (rtx *);
extern void rs6000_expand_vector_init (rtx, rtx);
extern void paired_expand_vector_init (rtx, rtx);
extern void rs6000_expand_vector_set (rtx, rtx, int);
......@@ -70,6 +71,8 @@ extern int insvdi_rshift_rlwimi_p (rtx, rtx, rtx);
extern int registers_ok_for_quad_peep (rtx, rtx);
extern int mems_ok_for_quad_peep (rtx, rtx);
extern bool gpr_or_gpr_p (rtx, rtx);
extern bool direct_move_p (rtx, rtx);
extern bool quad_load_store_p (rtx, rtx);
extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx,
enum reg_class);
extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
......
......@@ -126,7 +126,9 @@
(match_operand:VEC_L 1 "input_operand" ""))]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)
&& reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
&& gpr_or_gpr_p (operands[0], operands[1])
&& !direct_move_p (operands[0], operands[1])
&& !quad_load_store_p (operands[0], operands[1])"
[(pc)]
{
rs6000_split_multireg_move (operands[0], operands[1]);
......
......@@ -213,112 +213,31 @@
;; VSX moves
(define_insn "*vsx_mov<mode>"
[(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*Y,*r,*r,<VSr>,?wa,*r,v,wZ,v")
(match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,Y,r,j,j,j,W,v,wZ"))]
[(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,wQ,?&r,??Y,??r,??r,<VSr>,?wa,*r,v,wZ, v")
(match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,wQ,r,Y,r,j,j,j,W,v,wZ"))]
"VECTOR_MEM_VSX_P (<MODE>mode)
&& (register_operand (operands[0], <MODE>mode)
|| register_operand (operands[1], <MODE>mode))"
{
switch (which_alternative)
{
case 0:
case 3:
gcc_assert (MEM_P (operands[0])
&& GET_CODE (XEXP (operands[0], 0)) != PRE_INC
&& GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
&& GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
return "stx<VSm>x %x1,%y0";
case 1:
case 4:
gcc_assert (MEM_P (operands[1])
&& GET_CODE (XEXP (operands[1], 0)) != PRE_INC
&& GET_CODE (XEXP (operands[1], 0)) != PRE_DEC
&& GET_CODE (XEXP (operands[1], 0)) != PRE_MODIFY);
return "lx<VSm>x %x0,%y1";
case 2:
case 5:
return "xxlor %x0,%x1,%x1";
case 6:
case 7:
case 8:
case 11:
return "#";
case 9:
case 10:
return "xxlxor %x0,%x0,%x0";
case 12:
return output_vec_const_move (operands);
case 13:
gcc_assert (MEM_P (operands[0])
&& GET_CODE (XEXP (operands[0], 0)) != PRE_INC
&& GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
&& GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
return "stvx %1,%y0";
case 14:
gcc_assert (MEM_P (operands[0])
&& GET_CODE (XEXP (operands[0], 0)) != PRE_INC
&& GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
&& GET_CODE (XEXP (operands[0], 0)) != PRE_MODIFY);
return "lvx %0,%y1";
default:
gcc_unreachable ();
}
return rs6000_output_move_128bit (operands);
}
[(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,*,vecstore,vecload")])
[(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,load,store,store,load, *,vecsimple,vecsimple,*, *,vecstore,vecload")
(set_attr "length" "4,4,4,4,4,4,12,12,12,12,16,4,4,*,16,4,4")])
;; Unlike other VSX moves, allow the GPRs even for reloading, since a normal
;; use of TImode is for unions. However for plain data movement, slightly
;; favor the vector loads
(define_insn "*vsx_movti_64bit"
[(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,?Y,?r,?r,?r")
(match_operand:TI 1 "input_operand" "wa, Z,wa, O,W,wZ, v, r, Y, r, n"))]
[(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v,v,wZ,wQ,&r,Y,r,r,?r")
(match_operand:TI 1 "input_operand" "wa,Z,wa,O,W,wZ,v,r,wQ,r,Y,r,n"))]
"TARGET_POWERPC64 && VECTOR_MEM_VSX_P (TImode)
&& (register_operand (operands[0], TImode)
|| register_operand (operands[1], TImode))"
{
switch (which_alternative)
{
case 0:
return "stxvd2x %x1,%y0";
case 1:
return "lxvd2x %x0,%y1";
case 2:
return "xxlor %x0,%x1,%x1";
case 3:
return "xxlxor %x0,%x0,%x0";
case 4:
return output_vec_const_move (operands);
case 5:
return "stvx %1,%y0";
case 6:
return "lvx %0,%y1";
case 7:
case 8:
case 9:
case 10:
return "#";
default:
gcc_unreachable ();
}
return rs6000_output_move_128bit (operands);
}
[(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,*,*,*,*")
(set_attr "length" " 4, 4, 4, 4, 8, 4, 4,8,8,8,8")])
[(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store,load,store,load,*,*")
(set_attr "length" "4,4,4,4,16,4,4,8,8,8,8,8,8")])
(define_insn "*vsx_movti_32bit"
[(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,wa,v, v,wZ,Q,Y,????r,????r,????r,r")
......
2013-06-10 Michael Meissner <meissner@linux.vnet.ibm.com>
Pat Haugen <pthaugen@us.ibm.com>
Peter Bergner <bergner@vnet.ibm.com>
* gcc.target/powerpc/direct-move-vint1.c: New tests for power8
direct move instructions.
* gcc.target/powerpc/direct-move-vint2.c: Likewise.
* gcc.target/powerpc/direct-move.h: Likewise.
* gcc.target/powerpc/direct-move-float1.c: Likewise.
* gcc.target/powerpc/direct-move-float2.c: Likewise.
* gcc.target/powerpc/direct-move-double1.c: Likewise.
* gcc.target/powerpc/direct-move-double2.c: Likewise.
* gcc.target/powerpc/direct-move-long1.c: Likewise.
* gcc.target/powerpc/direct-move-long2.c: Likewise.
2013-06-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/52440
......
/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
/* { dg-final { scan-assembler-times "mtvsrd" 1 } } */
/* { dg-final { scan-assembler-times "mfvsrd" 1 } } */
/* Check code generation for direct move for long types. */
#define TYPE double
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#include "direct-move.h"
/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target p8vector_hw } */
/* { dg-options "-mcpu=power8 -O2" } */
/* Check whether we get the right bits for direct move at runtime. */
#define TYPE double
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#define DO_MAIN
#include "direct-move.h"
/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
/* { dg-final { scan-assembler-times "mtvsrd" 2 } } */
/* { dg-final { scan-assembler-times "mfvsrd" 2 } } */
/* { dg-final { scan-assembler-times "xscvdpspn" 2 } } */
/* { dg-final { scan-assembler-times "xscvspdpn" 2 } } */
/* Check code generation for direct move for long types. */
#define TYPE float
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#include "direct-move.h"
/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target p8vector_hw } */
/* { dg-options "-mcpu=power8 -O2" } */
/* Check whether we get the right bits for direct move at runtime. */
#define TYPE float
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#define DO_MAIN
#include "direct-move.h"
/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
/* { dg-final { scan-assembler-times "mtvsrd" 1 } } */
/* { dg-final { scan-assembler-times "mfvsrd" 2 } } */
/* Check code generation for direct move for long types. */
#define TYPE long
#define IS_INT 1
#define NO_ALTIVEC 1
#include "direct-move.h"
/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target p8vector_hw } */
/* { dg-options "-mcpu=power8 -O2" } */
/* Check whether we get the right bits for direct move at runtime. */
#define TYPE long
#define IS_INT 1
#define NO_ALTIVEC 1
#define DO_MAIN
#include "direct-move.h"
/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
/* { dg-final { scan-assembler-times "mtvsrd" 4 } } */
/* { dg-final { scan-assembler-times "mfvsrd" 4 } } */
/* Check code generation for direct move for long types. */
#define TYPE vector int
#include "direct-move.h"
/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target p8vector_hw } */
/* { dg-options "-mcpu=power8 -O2" } */
/* Check whether we get the right bits for direct move at runtime. */
#define TYPE vector int
#define DO_MAIN
#include "direct-move.h"
/* Test functions for direct move support. */
void __attribute__((__noinline__))
copy (TYPE *a, TYPE *b)
{
*b = *a;
}
#ifndef NO_GPR
void __attribute__((__noinline__))
load_gpr (TYPE *a, TYPE *b)
{
TYPE c = *a;
__asm__ ("# gpr, reg = %0" : "+b" (c));
*b = c;
}
#endif
#ifndef NO_FPR
void __attribute__((__noinline__))
load_fpr (TYPE *a, TYPE *b)
{
TYPE c = *a;
__asm__ ("# fpr, reg = %0" : "+d" (c));
*b = c;
}
#endif
#ifndef NO_ALTIVEC
void __attribute__((__noinline__))
load_altivec (TYPE *a, TYPE *b)
{
TYPE c = *a;
__asm__ ("# altivec, reg = %0" : "+v" (c));
*b = c;
}
#endif
#ifndef NO_VSX
void __attribute__((__noinline__))
load_vsx (TYPE *a, TYPE *b)
{
TYPE c = *a;
__asm__ ("# vsx, reg = %x0" : "+wa" (c));
*b = c;
}
#endif
#ifndef NO_GPR_TO_VSX
void __attribute__((__noinline__))
load_gpr_to_vsx (TYPE *a, TYPE *b)
{
TYPE c = *a;
TYPE d;
__asm__ ("# gpr, reg = %0" : "+b" (c));
d = c;
__asm__ ("# vsx, reg = %x0" : "+wa" (d));
*b = d;
}
#endif
#ifndef NO_VSX_TO_GPR
void __attribute__((__noinline__))
load_vsx_to_gpr (TYPE *a, TYPE *b)
{
TYPE c = *a;
TYPE d;
__asm__ ("# vsx, reg = %x0" : "+wa" (c));
d = c;
__asm__ ("# gpr, reg = %0" : "+b" (d));
*b = d;
}
#endif
#ifdef DO_MAIN
typedef void (fn_type (TYPE *, TYPE *));
struct test_struct {
fn_type *func;
const char *name;
};
const struct test_struct test_functions[] = {
{ copy, "copy" },
#ifndef NO_GPR
{ load_gpr, "load_gpr" },
#endif
#ifndef NO_FPR
{ load_fpr, "load_fpr" },
#endif
#ifndef NO_ALTIVEC
{ load_altivec, "load_altivec" },
#endif
#ifndef NO_VSX
{ load_vsx, "load_vsx" },
#endif
#ifndef NO_GPR_TO_VSX
{ load_gpr_to_vsx, "load_gpr_to_vsx" },
#endif
#ifndef NO_VSX_TO_GPR
{ load_vsx_to_gpr, "load_vsx_to_gpr" },
#endif
};
/* Test a given value for each of the functions. */
void __attribute__((__noinline__))
test_value (TYPE a)
{
size_t i;
for (i = 0; i < sizeof (test_functions) / sizeof (test_functions[0]); i++)
{
TYPE b;
test_functions[i].func (&a, &b);
if (memcmp ((void *)&a, (void *)&b, sizeof (TYPE)) != 0)
abort ();
}
}
/* Main program. */
int
main (void)
{
size_t i;
long j;
union {
TYPE value;
unsigned char bytes[sizeof (TYPE)];
} u;
#if IS_INT
TYPE value = (TYPE)-5;
for (i = 0; i < 12; i++)
{
test_value (value);
value++;
}
for (i = 0; i < 8*sizeof (TYPE); i++)
test_value (((TYPE)1) << i);
#elif IS_UNS
TYPE value = (TYPE)0;
for (i = 0; i < 10; i++)
{
test_value (value);
test_value (~ value);
value++;
}
for (i = 0; i < 8*sizeof (TYPE); i++)
test_value (((TYPE)1) << i);
#elif IS_FLOAT
TYPE value = (TYPE)-5;
for (i = 0; i < 12; i++)
{
test_value (value);
value++;
}
test_value ((TYPE)3.1415926535);
test_value ((TYPE)1.23456);
test_value ((TYPE)(-0.0));
test_value ((TYPE)NAN);
test_value ((TYPE)+INFINITY);
test_value ((TYPE)-INFINITY);
#else
for (j = 0; j < 10; j++)
{
for (i = 0; i < sizeof (TYPE); i++)
u.bytes[i] = (unsigned char) (random () >> 4);
test_value (u.value);
}
#endif
return 0;
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment