Commit fde66fde by Eric Botcazou Committed by Eric Botcazou

re PR target/59316 (gcc.dg/atomic/c11-atomic-exec-5.c FAILs on Solaris/SPARC)

	PR target/59316
	* config/sparc/sparc.h (SPARC_LOW_FE_EXCEPT_VALUES): Define.
	* config/sparc/sol2.h (SPARC_LOW_FE_EXCEPT_VALUES): Redefine.
	* config/sparc/sparc.c (TARGET_INIT_BUILTINS): Move around.
	(TARGET_BUILTIN_DECL): Define.
	(TARGET_ATOMIC_ASSIGN_EXPAND_FENV): Likewise.
	(sparc32_initialize_trampoline): Adjust call to gen_flush.
	(enum sparc_builtins): New enumeral type.
	(sparc_builtins): New static array.
	(sparc_builtins_icode): Likewise.
	(def_builtin): Accept a separate icode and save the result.
	(def_builtin_const): Likewise.
	(sparc_fpu_init_builtins): New function.
	(sparc_vis_init_builtins): Pass the builtin code.
	(sparc_init_builtins): Call it if TARGET_FPU.
	(sparc_builtin_decl): New function.
	(sparc_expand_builtin): Deal with SPARC_BUILTIN_{LD,ST}FSR.
	(sparc_handle_vis_mul8x16): Use the builtin code.
	(sparc_fold_builtin): Likewise.  Deal with SPARC_BUILTIN_{LD,ST}FSR
	and SPARC_BUILTIN_PDISTN.
	(compound_expr): New helper function.
	(sparc_atomic_assign_expand_fenv): New function.
	* config/sparc/sparc.md (unspecv): Reorder values, add UNSPECV_LDFSR
	and UNSPECV_STFSR.
	(flush, flushdi): Merge into single pattern.
	(ldfsr): New instruction.
	(stfsr): Likewise.

From-SVN: r205735
parent 2c8326a5
2013-12-06 Eric Botcazou <ebotcazou@adacore.com>
PR target/59316
* config/sparc/sparc.h (SPARC_LOW_FE_EXCEPT_VALUES): Define.
* config/sparc/sol2.h (SPARC_LOW_FE_EXCEPT_VALUES): Redefine.
* config/sparc/sparc.c (TARGET_INIT_BUILTINS): Move around.
(TARGET_BUILTIN_DECL): Define.
(TARGET_ATOMIC_ASSIGN_EXPAND_FENV): Likewise.
(sparc32_initialize_trampoline): Adjust call to gen_flush.
(enum sparc_builtins): New enumeral type.
(sparc_builtins): New static array.
(sparc_builtins_icode): Likewise.
(def_builtin): Accept a separate icode and save the result.
(def_builtin_const): Likewise.
(sparc_fpu_init_builtins): New function.
(sparc_vis_init_builtins): Pass the builtin code.
(sparc_init_builtins): Call it if TARGET_FPU.
(sparc_builtin_decl): New function.
(sparc_expand_builtin): Deal with SPARC_BUILTIN_{LD,ST}FSR.
(sparc_handle_vis_mul8x16): Use the builtin code.
(sparc_fold_builtin): Likewise. Deal with SPARC_BUILTIN_{LD,ST}FSR
and SPARC_BUILTIN_PDISTN.
(compound_expr): New helper function.
(sparc_atomic_assign_expand_fenv): New function.
* config/sparc/sparc.md (unspecv): Reorder values, add UNSPECV_LDFSR
and UNSPECV_STFSR.
(flush, flushdi): Merge into single pattern.
(ldfsr): New instruction.
(stfsr): Likewise.
2013-12-06 Oleg Endo <olegendo@gcc.gnu.org>
* asan.c: Remove struct tags when referring to class varpool_node.
......@@ -406,3 +406,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#undef SUN_INTEGER_MULTIPLY_64
#define SUN_INTEGER_MULTIPLY_64 1
#undef SPARC_LOW_FE_EXCEPT_VALUES
#define SPARC_LOW_FE_EXCEPT_VALUES 1
......@@ -570,11 +570,11 @@ static void emit_hard_tfmode_operation (enum rtx_code, rtx *);
static bool sparc_function_ok_for_sibcall (tree, tree);
static void sparc_init_libfuncs (void);
static void sparc_init_builtins (void);
static void sparc_fpu_init_builtins (void);
static void sparc_vis_init_builtins (void);
static tree sparc_builtin_decl (unsigned, bool);
static rtx sparc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
static tree sparc_fold_builtin (tree, int, tree *, bool);
static int sparc_vis_mul8x16 (int, int);
static void sparc_handle_vis_mul8x16 (tree *, int, tree, tree, tree);
static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
......@@ -638,6 +638,7 @@ static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
enum machine_mode,
secondary_reload_info *);
static enum machine_mode sparc_cstore_mode (enum insn_code icode);
static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
#ifdef SUBTARGET_ATTRIBUTE_TABLE
/* Table of valid machine attributes. */
......@@ -693,8 +694,6 @@ char sparc_hard_reg_printed[8];
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS sparc_init_libfuncs
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS sparc_init_builtins
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS sparc_legitimize_address
......@@ -703,6 +702,10 @@ char sparc_hard_reg_printed[8];
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
#define TARGET_MODE_DEPENDENT_ADDRESS_P sparc_mode_dependent_address_p
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS sparc_init_builtins
#undef TARGET_BUILTIN_DECL
#define TARGET_BUILTIN_DECL sparc_builtin_decl
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN sparc_expand_builtin
#undef TARGET_FOLD_BUILTIN
......@@ -843,6 +846,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_CSTORE_MODE
#define TARGET_CSTORE_MODE sparc_cstore_mode
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV sparc_atomic_assign_expand_fenv
struct gcc_target targetm = TARGET_INITIALIZER;
/* Return the memory reference contained in X if any, zero otherwise. */
......@@ -9237,14 +9243,14 @@ sparc32_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt)
/* On UltraSPARC a flush flushes an entire cache line. The trampoline is
aligned on a 16 byte boundary so one flush clears it all. */
emit_insn (gen_flush (validize_mem (adjust_address (m_tramp, SImode, 0))));
emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 0))));
if (sparc_cpu != PROCESSOR_ULTRASPARC
&& sparc_cpu != PROCESSOR_ULTRASPARC3
&& sparc_cpu != PROCESSOR_NIAGARA
&& sparc_cpu != PROCESSOR_NIAGARA2
&& sparc_cpu != PROCESSOR_NIAGARA3
&& sparc_cpu != PROCESSOR_NIAGARA4)
emit_insn (gen_flush (validize_mem (adjust_address (m_tramp, SImode, 8))));
emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 8))));
/* Call __enable_execute_stack after writing onto the stack to make sure
the stack address is accessible. */
......@@ -9969,15 +9975,145 @@ sparc_init_libfuncs (void)
}
}
static tree def_builtin(const char *name, int code, tree type)
/* SPARC builtins. */
enum sparc_builtins
{
/* FPU builtins. */
SPARC_BUILTIN_LDFSR,
SPARC_BUILTIN_STFSR,
/* VIS 1.0 builtins. */
SPARC_BUILTIN_FPACK16,
SPARC_BUILTIN_FPACK32,
SPARC_BUILTIN_FPACKFIX,
SPARC_BUILTIN_FEXPAND,
SPARC_BUILTIN_FPMERGE,
SPARC_BUILTIN_FMUL8X16,
SPARC_BUILTIN_FMUL8X16AU,
SPARC_BUILTIN_FMUL8X16AL,
SPARC_BUILTIN_FMUL8SUX16,
SPARC_BUILTIN_FMUL8ULX16,
SPARC_BUILTIN_FMULD8SUX16,
SPARC_BUILTIN_FMULD8ULX16,
SPARC_BUILTIN_FALIGNDATAV4HI,
SPARC_BUILTIN_FALIGNDATAV8QI,
SPARC_BUILTIN_FALIGNDATAV2SI,
SPARC_BUILTIN_FALIGNDATADI,
SPARC_BUILTIN_WRGSR,
SPARC_BUILTIN_RDGSR,
SPARC_BUILTIN_ALIGNADDR,
SPARC_BUILTIN_ALIGNADDRL,
SPARC_BUILTIN_PDIST,
SPARC_BUILTIN_EDGE8,
SPARC_BUILTIN_EDGE8L,
SPARC_BUILTIN_EDGE16,
SPARC_BUILTIN_EDGE16L,
SPARC_BUILTIN_EDGE32,
SPARC_BUILTIN_EDGE32L,
SPARC_BUILTIN_FCMPLE16,
SPARC_BUILTIN_FCMPLE32,
SPARC_BUILTIN_FCMPNE16,
SPARC_BUILTIN_FCMPNE32,
SPARC_BUILTIN_FCMPGT16,
SPARC_BUILTIN_FCMPGT32,
SPARC_BUILTIN_FCMPEQ16,
SPARC_BUILTIN_FCMPEQ32,
SPARC_BUILTIN_FPADD16,
SPARC_BUILTIN_FPADD16S,
SPARC_BUILTIN_FPADD32,
SPARC_BUILTIN_FPADD32S,
SPARC_BUILTIN_FPSUB16,
SPARC_BUILTIN_FPSUB16S,
SPARC_BUILTIN_FPSUB32,
SPARC_BUILTIN_FPSUB32S,
SPARC_BUILTIN_ARRAY8,
SPARC_BUILTIN_ARRAY16,
SPARC_BUILTIN_ARRAY32,
/* VIS 2.0 builtins. */
SPARC_BUILTIN_EDGE8N,
SPARC_BUILTIN_EDGE8LN,
SPARC_BUILTIN_EDGE16N,
SPARC_BUILTIN_EDGE16LN,
SPARC_BUILTIN_EDGE32N,
SPARC_BUILTIN_EDGE32LN,
SPARC_BUILTIN_BMASK,
SPARC_BUILTIN_BSHUFFLEV4HI,
SPARC_BUILTIN_BSHUFFLEV8QI,
SPARC_BUILTIN_BSHUFFLEV2SI,
SPARC_BUILTIN_BSHUFFLEDI,
/* VIS 3.0 builtins. */
SPARC_BUILTIN_CMASK8,
SPARC_BUILTIN_CMASK16,
SPARC_BUILTIN_CMASK32,
SPARC_BUILTIN_FCHKSM16,
SPARC_BUILTIN_FSLL16,
SPARC_BUILTIN_FSLAS16,
SPARC_BUILTIN_FSRL16,
SPARC_BUILTIN_FSRA16,
SPARC_BUILTIN_FSLL32,
SPARC_BUILTIN_FSLAS32,
SPARC_BUILTIN_FSRL32,
SPARC_BUILTIN_FSRA32,
SPARC_BUILTIN_PDISTN,
SPARC_BUILTIN_FMEAN16,
SPARC_BUILTIN_FPADD64,
SPARC_BUILTIN_FPSUB64,
SPARC_BUILTIN_FPADDS16,
SPARC_BUILTIN_FPADDS16S,
SPARC_BUILTIN_FPSUBS16,
SPARC_BUILTIN_FPSUBS16S,
SPARC_BUILTIN_FPADDS32,
SPARC_BUILTIN_FPADDS32S,
SPARC_BUILTIN_FPSUBS32,
SPARC_BUILTIN_FPSUBS32S,
SPARC_BUILTIN_FUCMPLE8,
SPARC_BUILTIN_FUCMPNE8,
SPARC_BUILTIN_FUCMPGT8,
SPARC_BUILTIN_FUCMPEQ8,
SPARC_BUILTIN_FHADDS,
SPARC_BUILTIN_FHADDD,
SPARC_BUILTIN_FHSUBS,
SPARC_BUILTIN_FHSUBD,
SPARC_BUILTIN_FNHADDS,
SPARC_BUILTIN_FNHADDD,
SPARC_BUILTIN_UMULXHI,
SPARC_BUILTIN_XMULX,
SPARC_BUILTIN_XMULXHI,
SPARC_BUILTIN_MAX
};
static GTY (()) tree sparc_builtins[(int) SPARC_BUILTIN_MAX];
static enum insn_code sparc_builtins_icode[(int) SPARC_BUILTIN_MAX];
/* Add a SPARC builtin function with NAME, ICODE, CODE and TYPE. Return the
function decl or NULL_TREE if the builtin was not added. */
static tree
def_builtin (const char *name, enum insn_code icode, enum sparc_builtins code,
tree type)
{
return add_builtin_function(name, type, code, BUILT_IN_MD, NULL,
NULL_TREE);
tree t
= add_builtin_function (name, type, code, BUILT_IN_MD, NULL, NULL_TREE);
if (t)
{
sparc_builtins[code] = t;
sparc_builtins_icode[code] = icode;
}
return t;
}
static tree def_builtin_const(const char *name, int code, tree type)
/* Likewise, but also marks the function as "const". */
static tree
def_builtin_const (const char *name, enum insn_code icode,
enum sparc_builtins code, tree type)
{
tree t = def_builtin(name, code, type);
tree t = def_builtin (name, icode, code, type);
if (t)
TREE_READONLY (t) = 1;
......@@ -9991,11 +10127,28 @@ static tree def_builtin_const(const char *name, int code, tree type)
static void
sparc_init_builtins (void)
{
if (TARGET_FPU)
sparc_fpu_init_builtins ();
if (TARGET_VIS)
sparc_vis_init_builtins ();
}
/* Create builtin functions for VIS 1.0 instructions. */
/* Create builtin functions for FPU instructions. */
static void
sparc_fpu_init_builtins (void)
{
tree ftype
= build_function_type_list (void_type_node,
build_pointer_type (unsigned_type_node), 0);
def_builtin ("__builtin_load_fsr", CODE_FOR_ldfsr,
SPARC_BUILTIN_LDFSR, ftype);
def_builtin ("__builtin_store_fsr", CODE_FOR_stfsr,
SPARC_BUILTIN_STFSR, ftype);
}
/* Create builtin functions for VIS instructions. */
static void
sparc_vis_init_builtins (void)
......@@ -10069,223 +10222,225 @@ sparc_vis_init_builtins (void)
/* Packing and expanding vectors. */
def_builtin ("__builtin_vis_fpack16", CODE_FOR_fpack16_vis,
v4qi_ftype_v4hi);
SPARC_BUILTIN_FPACK16, v4qi_ftype_v4hi);
def_builtin ("__builtin_vis_fpack32", CODE_FOR_fpack32_vis,
v8qi_ftype_v2si_v8qi);
SPARC_BUILTIN_FPACK32, v8qi_ftype_v2si_v8qi);
def_builtin ("__builtin_vis_fpackfix", CODE_FOR_fpackfix_vis,
v2hi_ftype_v2si);
SPARC_BUILTIN_FPACKFIX, v2hi_ftype_v2si);
def_builtin_const ("__builtin_vis_fexpand", CODE_FOR_fexpand_vis,
v4hi_ftype_v4qi);
SPARC_BUILTIN_FEXPAND, v4hi_ftype_v4qi);
def_builtin_const ("__builtin_vis_fpmerge", CODE_FOR_fpmerge_vis,
v8qi_ftype_v4qi_v4qi);
SPARC_BUILTIN_FPMERGE, v8qi_ftype_v4qi_v4qi);
/* Multiplications. */
def_builtin_const ("__builtin_vis_fmul8x16", CODE_FOR_fmul8x16_vis,
v4hi_ftype_v4qi_v4hi);
SPARC_BUILTIN_FMUL8X16, v4hi_ftype_v4qi_v4hi);
def_builtin_const ("__builtin_vis_fmul8x16au", CODE_FOR_fmul8x16au_vis,
v4hi_ftype_v4qi_v2hi);
SPARC_BUILTIN_FMUL8X16AU, v4hi_ftype_v4qi_v2hi);
def_builtin_const ("__builtin_vis_fmul8x16al", CODE_FOR_fmul8x16al_vis,
v4hi_ftype_v4qi_v2hi);
SPARC_BUILTIN_FMUL8X16AL, v4hi_ftype_v4qi_v2hi);
def_builtin_const ("__builtin_vis_fmul8sux16", CODE_FOR_fmul8sux16_vis,
v4hi_ftype_v8qi_v4hi);
SPARC_BUILTIN_FMUL8SUX16, v4hi_ftype_v8qi_v4hi);
def_builtin_const ("__builtin_vis_fmul8ulx16", CODE_FOR_fmul8ulx16_vis,
v4hi_ftype_v8qi_v4hi);
SPARC_BUILTIN_FMUL8ULX16, v4hi_ftype_v8qi_v4hi);
def_builtin_const ("__builtin_vis_fmuld8sux16", CODE_FOR_fmuld8sux16_vis,
v2si_ftype_v4qi_v2hi);
SPARC_BUILTIN_FMULD8SUX16, v2si_ftype_v4qi_v2hi);
def_builtin_const ("__builtin_vis_fmuld8ulx16", CODE_FOR_fmuld8ulx16_vis,
v2si_ftype_v4qi_v2hi);
SPARC_BUILTIN_FMULD8ULX16, v2si_ftype_v4qi_v2hi);
/* Data aligning. */
def_builtin ("__builtin_vis_faligndatav4hi", CODE_FOR_faligndatav4hi_vis,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FALIGNDATAV4HI, v4hi_ftype_v4hi_v4hi);
def_builtin ("__builtin_vis_faligndatav8qi", CODE_FOR_faligndatav8qi_vis,
v8qi_ftype_v8qi_v8qi);
SPARC_BUILTIN_FALIGNDATAV8QI, v8qi_ftype_v8qi_v8qi);
def_builtin ("__builtin_vis_faligndatav2si", CODE_FOR_faligndatav2si_vis,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FALIGNDATAV2SI, v2si_ftype_v2si_v2si);
def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatav1di_vis,
di_ftype_di_di);
SPARC_BUILTIN_FALIGNDATADI, di_ftype_di_di);
def_builtin ("__builtin_vis_write_gsr", CODE_FOR_wrgsr_vis,
void_ftype_di);
SPARC_BUILTIN_WRGSR, void_ftype_di);
def_builtin ("__builtin_vis_read_gsr", CODE_FOR_rdgsr_vis,
di_ftype_void);
SPARC_BUILTIN_RDGSR, di_ftype_void);
if (TARGET_ARCH64)
{
def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrdi_vis,
ptr_ftype_ptr_di);
SPARC_BUILTIN_ALIGNADDR, ptr_ftype_ptr_di);
def_builtin ("__builtin_vis_alignaddrl", CODE_FOR_alignaddrldi_vis,
ptr_ftype_ptr_di);
SPARC_BUILTIN_ALIGNADDRL, ptr_ftype_ptr_di);
}
else
{
def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrsi_vis,
ptr_ftype_ptr_si);
SPARC_BUILTIN_ALIGNADDR, ptr_ftype_ptr_si);
def_builtin ("__builtin_vis_alignaddrl", CODE_FOR_alignaddrlsi_vis,
ptr_ftype_ptr_si);
SPARC_BUILTIN_ALIGNADDRL, ptr_ftype_ptr_si);
}
/* Pixel distance. */
def_builtin_const ("__builtin_vis_pdist", CODE_FOR_pdist_vis,
di_ftype_v8qi_v8qi_di);
SPARC_BUILTIN_PDIST, di_ftype_v8qi_v8qi_di);
/* Edge handling. */
if (TARGET_ARCH64)
{
def_builtin_const ("__builtin_vis_edge8", CODE_FOR_edge8di_vis,
di_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE8, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge8l", CODE_FOR_edge8ldi_vis,
di_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE8L, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16", CODE_FOR_edge16di_vis,
di_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE16, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16l", CODE_FOR_edge16ldi_vis,
di_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE16L, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32", CODE_FOR_edge32di_vis,
di_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE32, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32ldi_vis,
di_ftype_ptr_ptr);
if (TARGET_VIS2)
{
def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8ndi_vis,
di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lndi_vis,
di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16ndi_vis,
di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lndi_vis,
di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32ndi_vis,
di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lndi_vis,
di_ftype_ptr_ptr);
}
SPARC_BUILTIN_EDGE32L, di_ftype_ptr_ptr);
}
else
{
def_builtin_const ("__builtin_vis_edge8", CODE_FOR_edge8si_vis,
si_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE8, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge8l", CODE_FOR_edge8lsi_vis,
si_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE8L, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16", CODE_FOR_edge16si_vis,
si_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE16, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16l", CODE_FOR_edge16lsi_vis,
si_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE16L, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32", CODE_FOR_edge32si_vis,
si_ftype_ptr_ptr);
SPARC_BUILTIN_EDGE32, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32lsi_vis,
si_ftype_ptr_ptr);
if (TARGET_VIS2)
{
def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8nsi_vis,
si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lnsi_vis,
si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16nsi_vis,
si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lnsi_vis,
si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32nsi_vis,
si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lnsi_vis,
si_ftype_ptr_ptr);
}
SPARC_BUILTIN_EDGE32L, si_ftype_ptr_ptr);
}
/* Pixel compare. */
if (TARGET_ARCH64)
{
def_builtin_const ("__builtin_vis_fcmple16", CODE_FOR_fcmple16di_vis,
di_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPLE16, di_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmple32", CODE_FOR_fcmple32di_vis,
di_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPLE32, di_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fcmpne16", CODE_FOR_fcmpne16di_vis,
di_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPNE16, di_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmpne32", CODE_FOR_fcmpne32di_vis,
di_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPNE32, di_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fcmpgt16", CODE_FOR_fcmpgt16di_vis,
di_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPGT16, di_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmpgt32", CODE_FOR_fcmpgt32di_vis,
di_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPGT32, di_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fcmpeq16", CODE_FOR_fcmpeq16di_vis,
di_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPEQ16, di_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmpeq32", CODE_FOR_fcmpeq32di_vis,
di_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPEQ32, di_ftype_v2si_v2si);
}
else
{
def_builtin_const ("__builtin_vis_fcmple16", CODE_FOR_fcmple16si_vis,
si_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPLE16, si_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmple32", CODE_FOR_fcmple32si_vis,
si_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPLE32, si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fcmpne16", CODE_FOR_fcmpne16si_vis,
si_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPNE16, si_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmpne32", CODE_FOR_fcmpne32si_vis,
si_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPNE32, si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fcmpgt16", CODE_FOR_fcmpgt16si_vis,
si_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPGT16, si_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmpgt32", CODE_FOR_fcmpgt32si_vis,
si_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPGT32, si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fcmpeq16", CODE_FOR_fcmpeq16si_vis,
si_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCMPEQ16, si_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fcmpeq32", CODE_FOR_fcmpeq32si_vis,
si_ftype_v2si_v2si);
SPARC_BUILTIN_FCMPEQ32, si_ftype_v2si_v2si);
}
/* Addition and subtraction. */
def_builtin_const ("__builtin_vis_fpadd16", CODE_FOR_addv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FPADD16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fpadd16s", CODE_FOR_addv2hi3,
v2hi_ftype_v2hi_v2hi);
SPARC_BUILTIN_FPADD16S, v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpadd32", CODE_FOR_addv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FPADD32, v2si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fpadd32s", CODE_FOR_addv1si3,
v1si_ftype_v1si_v1si);
SPARC_BUILTIN_FPADD32S, v1si_ftype_v1si_v1si);
def_builtin_const ("__builtin_vis_fpsub16", CODE_FOR_subv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FPSUB16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fpsub16s", CODE_FOR_subv2hi3,
v2hi_ftype_v2hi_v2hi);
SPARC_BUILTIN_FPSUB16S, v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpsub32", CODE_FOR_subv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FPSUB32, v2si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fpsub32s", CODE_FOR_subv1si3,
v1si_ftype_v1si_v1si);
SPARC_BUILTIN_FPSUB32S, v1si_ftype_v1si_v1si);
/* Three-dimensional array addressing. */
if (TARGET_ARCH64)
{
def_builtin_const ("__builtin_vis_array8", CODE_FOR_array8di_vis,
di_ftype_di_di);
SPARC_BUILTIN_ARRAY8, di_ftype_di_di);
def_builtin_const ("__builtin_vis_array16", CODE_FOR_array16di_vis,
di_ftype_di_di);
SPARC_BUILTIN_ARRAY16, di_ftype_di_di);
def_builtin_const ("__builtin_vis_array32", CODE_FOR_array32di_vis,
di_ftype_di_di);
SPARC_BUILTIN_ARRAY32, di_ftype_di_di);
}
else
{
def_builtin_const ("__builtin_vis_array8", CODE_FOR_array8si_vis,
si_ftype_si_si);
SPARC_BUILTIN_ARRAY8, si_ftype_si_si);
def_builtin_const ("__builtin_vis_array16", CODE_FOR_array16si_vis,
si_ftype_si_si);
SPARC_BUILTIN_ARRAY16, si_ftype_si_si);
def_builtin_const ("__builtin_vis_array32", CODE_FOR_array32si_vis,
si_ftype_si_si);
}
SPARC_BUILTIN_ARRAY32, si_ftype_si_si);
}
if (TARGET_VIS2)
{
/* Byte mask and shuffle */
/* Edge handling. */
if (TARGET_ARCH64)
{
def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8ndi_vis,
SPARC_BUILTIN_EDGE8N, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lndi_vis,
SPARC_BUILTIN_EDGE8LN, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16ndi_vis,
SPARC_BUILTIN_EDGE16N, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lndi_vis,
SPARC_BUILTIN_EDGE16LN, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32ndi_vis,
SPARC_BUILTIN_EDGE32N, di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lndi_vis,
SPARC_BUILTIN_EDGE32LN, di_ftype_ptr_ptr);
}
else
{
def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8nsi_vis,
SPARC_BUILTIN_EDGE8N, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lnsi_vis,
SPARC_BUILTIN_EDGE8LN, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16nsi_vis,
SPARC_BUILTIN_EDGE16N, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lnsi_vis,
SPARC_BUILTIN_EDGE16LN, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32nsi_vis,
SPARC_BUILTIN_EDGE32N, si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lnsi_vis,
SPARC_BUILTIN_EDGE32LN, si_ftype_ptr_ptr);
}
/* Byte mask and shuffle. */
if (TARGET_ARCH64)
def_builtin ("__builtin_vis_bmask", CODE_FOR_bmaskdi_vis,
di_ftype_di_di);
SPARC_BUILTIN_BMASK, di_ftype_di_di);
else
def_builtin ("__builtin_vis_bmask", CODE_FOR_bmasksi_vis,
si_ftype_si_si);
SPARC_BUILTIN_BMASK, si_ftype_si_si);
def_builtin ("__builtin_vis_bshufflev4hi", CODE_FOR_bshufflev4hi_vis,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_BSHUFFLEV4HI, v4hi_ftype_v4hi_v4hi);
def_builtin ("__builtin_vis_bshufflev8qi", CODE_FOR_bshufflev8qi_vis,
v8qi_ftype_v8qi_v8qi);
SPARC_BUILTIN_BSHUFFLEV8QI, v8qi_ftype_v8qi_v8qi);
def_builtin ("__builtin_vis_bshufflev2si", CODE_FOR_bshufflev2si_vis,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_BSHUFFLEV2SI, v2si_ftype_v2si_v2si);
def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshufflev1di_vis,
di_ftype_di_di);
SPARC_BUILTIN_BSHUFFLEDI, di_ftype_di_di);
}
if (TARGET_VIS3)
......@@ -10293,120 +10448,130 @@ sparc_vis_init_builtins (void)
if (TARGET_ARCH64)
{
def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8di_vis,
void_ftype_di);
SPARC_BUILTIN_CMASK8, void_ftype_di);
def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16di_vis,
void_ftype_di);
SPARC_BUILTIN_CMASK16, void_ftype_di);
def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32di_vis,
void_ftype_di);
SPARC_BUILTIN_CMASK32, void_ftype_di);
}
else
{
def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8si_vis,
void_ftype_si);
SPARC_BUILTIN_CMASK8, void_ftype_si);
def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16si_vis,
void_ftype_si);
SPARC_BUILTIN_CMASK16, void_ftype_si);
def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32si_vis,
void_ftype_si);
SPARC_BUILTIN_CMASK32, void_ftype_si);
}
def_builtin_const ("__builtin_vis_fchksm16", CODE_FOR_fchksm16_vis,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FCHKSM16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_vashlv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FSLL16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_vssashlv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FSLAS16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_vlshrv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FSRL16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_vashrv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FSRA16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_vashlv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FSLL32, v2si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_vssashlv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FSLAS32, v2si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_vlshrv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FSRL32, v2si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_vashrv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FSRA32, v2si_ftype_v2si_v2si);
if (TARGET_ARCH64)
def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistndi_vis,
di_ftype_v8qi_v8qi);
SPARC_BUILTIN_PDISTN, di_ftype_v8qi_v8qi);
else
def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistnsi_vis,
si_ftype_v8qi_v8qi);
SPARC_BUILTIN_PDISTN, si_ftype_v8qi_v8qi);
def_builtin_const ("__builtin_vis_fmean16", CODE_FOR_fmean16_vis,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FMEAN16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fpadd64", CODE_FOR_fpadd64_vis,
di_ftype_di_di);
SPARC_BUILTIN_FPADD64, di_ftype_di_di);
def_builtin_const ("__builtin_vis_fpsub64", CODE_FOR_fpsub64_vis,
di_ftype_di_di);
SPARC_BUILTIN_FPSUB64, di_ftype_di_di);
def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_ssaddv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FPADDS16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_ssaddv2hi3,
v2hi_ftype_v2hi_v2hi);
SPARC_BUILTIN_FPADDS16S, v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_sssubv4hi3,
v4hi_ftype_v4hi_v4hi);
SPARC_BUILTIN_FPSUBS16, v4hi_ftype_v4hi_v4hi);
def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_sssubv2hi3,
v2hi_ftype_v2hi_v2hi);
SPARC_BUILTIN_FPSUBS16S, v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_ssaddv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FPADDS32, v2si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_ssaddv1si3,
v1si_ftype_v1si_v1si);
SPARC_BUILTIN_FPADDS32S, v1si_ftype_v1si_v1si);
def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_sssubv2si3,
v2si_ftype_v2si_v2si);
SPARC_BUILTIN_FPSUBS32, v2si_ftype_v2si_v2si);
def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_sssubv1si3,
v1si_ftype_v1si_v1si);
SPARC_BUILTIN_FPSUBS32S, v1si_ftype_v1si_v1si);
if (TARGET_ARCH64)
{
def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8di_vis,
di_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPLE8, di_ftype_v8qi_v8qi);
def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8di_vis,
di_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPNE8, di_ftype_v8qi_v8qi);
def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8di_vis,
di_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPGT8, di_ftype_v8qi_v8qi);
def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8di_vis,
di_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPEQ8, di_ftype_v8qi_v8qi);
}
else
{
def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8si_vis,
si_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPLE8, si_ftype_v8qi_v8qi);
def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8si_vis,
si_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPNE8, si_ftype_v8qi_v8qi);
def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8si_vis,
si_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPGT8, si_ftype_v8qi_v8qi);
def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8si_vis,
si_ftype_v8qi_v8qi);
SPARC_BUILTIN_FUCMPEQ8, si_ftype_v8qi_v8qi);
}
def_builtin_const ("__builtin_vis_fhadds", CODE_FOR_fhaddsf_vis,
sf_ftype_sf_sf);
SPARC_BUILTIN_FHADDS, sf_ftype_sf_sf);
def_builtin_const ("__builtin_vis_fhaddd", CODE_FOR_fhadddf_vis,
df_ftype_df_df);
SPARC_BUILTIN_FHADDD, df_ftype_df_df);
def_builtin_const ("__builtin_vis_fhsubs", CODE_FOR_fhsubsf_vis,
sf_ftype_sf_sf);
SPARC_BUILTIN_FHSUBS, sf_ftype_sf_sf);
def_builtin_const ("__builtin_vis_fhsubd", CODE_FOR_fhsubdf_vis,
df_ftype_df_df);
SPARC_BUILTIN_FHSUBD, df_ftype_df_df);
def_builtin_const ("__builtin_vis_fnhadds", CODE_FOR_fnhaddsf_vis,
sf_ftype_sf_sf);
SPARC_BUILTIN_FNHADDS, sf_ftype_sf_sf);
def_builtin_const ("__builtin_vis_fnhaddd", CODE_FOR_fnhadddf_vis,
df_ftype_df_df);
SPARC_BUILTIN_FNHADDD, df_ftype_df_df);
def_builtin_const ("__builtin_vis_umulxhi", CODE_FOR_umulxhi_vis,
di_ftype_di_di);
SPARC_BUILTIN_UMULXHI, di_ftype_di_di);
def_builtin_const ("__builtin_vis_xmulx", CODE_FOR_xmulx_vis,
di_ftype_di_di);
SPARC_BUILTIN_XMULX, di_ftype_di_di);
def_builtin_const ("__builtin_vis_xmulxhi", CODE_FOR_xmulxhi_vis,
di_ftype_di_di);
SPARC_BUILTIN_XMULXHI, di_ftype_di_di);
}
}
/* Handle TARGET_EXPAND_BUILTIN target hook.
Expand builtin functions for sparc intrinsics. */
/* Implement TARGET_BUILTIN_DECL hook. */
static tree
sparc_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
{
if (code >= SPARC_BUILTIN_MAX)
return error_mark_node;
return sparc_builtins[code];
}
/* Implemented TARGET_EXPAND_BUILTIN hook. */
static rtx
sparc_expand_builtin (tree exp, rtx target,
......@@ -10414,15 +10579,14 @@ sparc_expand_builtin (tree exp, rtx target,
enum machine_mode tmode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
tree arg;
call_expr_arg_iterator iter;
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int icode = DECL_FUNCTION_CODE (fndecl);
rtx pat, op[4];
enum sparc_builtins code = (enum sparc_builtins) DECL_FUNCTION_CODE (fndecl);
enum insn_code icode = sparc_builtins_icode[code];
bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
call_expr_arg_iterator iter;
int arg_count = 0;
bool nonvoid;
nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
rtx pat, op[4];
tree arg;
if (nonvoid)
{
......@@ -10434,6 +10598,7 @@ sparc_expand_builtin (tree exp, rtx target,
else
op[0] = target;
}
FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
{
const struct insn_operand_data *insn_op;
......@@ -10447,11 +10612,22 @@ sparc_expand_builtin (tree exp, rtx target,
insn_op = &insn_data[icode].operand[idx];
op[arg_count] = expand_normal (arg);
if (insn_op->mode == V1DImode
&& GET_MODE (op[arg_count]) == DImode)
if (code == SPARC_BUILTIN_LDFSR || code == SPARC_BUILTIN_STFSR)
{
if (!address_operand (op[arg_count], SImode))
{
op[arg_count] = convert_memory_address (Pmode, op[arg_count]);
op[arg_count] = copy_addr_to_reg (op[arg_count]);
}
op[arg_count] = gen_rtx_MEM (SImode, op[arg_count]);
}
else if (insn_op->mode == V1DImode
&& GET_MODE (op[arg_count]) == DImode)
op[arg_count] = gen_lowpart (V1DImode, op[arg_count]);
else if (insn_op->mode == V1SImode
&& GET_MODE (op[arg_count]) == SImode)
&& GET_MODE (op[arg_count]) == SImode)
op[arg_count] = gen_lowpart (V1SImode, op[arg_count]);
if (! (*insn_data[icode].operand[idx].predicate) (op[arg_count],
......@@ -10485,12 +10661,11 @@ sparc_expand_builtin (tree exp, rtx target,
emit_insn (pat);
if (nonvoid)
return op[0];
else
return const0_rtx;
return (nonvoid ? op[0] : const0_rtx);
}
/* Return the upper 16 bits of the 8x16 multiplication. */
static int
sparc_vis_mul8x16 (int e8, int e16)
{
......@@ -10501,15 +10676,15 @@ sparc_vis_mul8x16 (int e8, int e16)
the result into the array N_ELTS, whose elements are of INNER_TYPE. */
static void
sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type,
tree cst0, tree cst1)
sparc_handle_vis_mul8x16 (tree *n_elts, enum sparc_builtins fncode,
tree inner_type, tree cst0, tree cst1)
{
unsigned i, num = VECTOR_CST_NELTS (cst0);
int scale;
switch (fncode)
{
case CODE_FOR_fmul8x16_vis:
case SPARC_BUILTIN_FMUL8X16:
for (i = 0; i < num; ++i)
{
int val
......@@ -10519,7 +10694,7 @@ sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type,
}
break;
case CODE_FOR_fmul8x16au_vis:
case SPARC_BUILTIN_FMUL8X16AU:
scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (cst1, 0));
for (i = 0; i < num; ++i)
......@@ -10531,7 +10706,7 @@ sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type,
}
break;
case CODE_FOR_fmul8x16al_vis:
case SPARC_BUILTIN_FMUL8X16AL:
scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (cst1, 1));
for (i = 0; i < num; ++i)
......@@ -10548,7 +10723,8 @@ sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type,
}
}
/* Handle TARGET_FOLD_BUILTIN target hook.
/* Implement TARGET_FOLD_BUILTIN hook.
Fold builtin functions for SPARC intrinsics. If IGNORE is true the
result of the function call is ignored. NULL_TREE is returned if the
function could not be folded. */
......@@ -10557,34 +10733,30 @@ static tree
sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
tree *args, bool ignore)
{
tree arg0, arg1, arg2;
enum sparc_builtins code = (enum sparc_builtins) DECL_FUNCTION_CODE (fndecl);
tree rtype = TREE_TYPE (TREE_TYPE (fndecl));
enum insn_code icode = (enum insn_code) DECL_FUNCTION_CODE (fndecl);
tree arg0, arg1, arg2;
if (ignore)
{
/* Note that a switch statement instead of the sequence of tests would
be incorrect as many of the CODE_FOR values could be CODE_FOR_nothing
and that would yield multiple alternatives with identical values. */
if (icode == CODE_FOR_alignaddrsi_vis
|| icode == CODE_FOR_alignaddrdi_vis
|| icode == CODE_FOR_wrgsr_vis
|| icode == CODE_FOR_bmasksi_vis
|| icode == CODE_FOR_bmaskdi_vis
|| icode == CODE_FOR_cmask8si_vis
|| icode == CODE_FOR_cmask8di_vis
|| icode == CODE_FOR_cmask16si_vis
|| icode == CODE_FOR_cmask16di_vis
|| icode == CODE_FOR_cmask32si_vis
|| icode == CODE_FOR_cmask32di_vis)
;
else
switch (code)
{
case SPARC_BUILTIN_LDFSR:
case SPARC_BUILTIN_STFSR:
case SPARC_BUILTIN_ALIGNADDR:
case SPARC_BUILTIN_WRGSR:
case SPARC_BUILTIN_BMASK:
case SPARC_BUILTIN_CMASK8:
case SPARC_BUILTIN_CMASK16:
case SPARC_BUILTIN_CMASK32:
break;
default:
return build_zero_cst (rtype);
}
}
switch (icode)
switch (code)
{
case CODE_FOR_fexpand_vis:
case SPARC_BUILTIN_FEXPAND:
arg0 = args[0];
STRIP_NOPS (arg0);
......@@ -10603,9 +10775,9 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
}
break;
case CODE_FOR_fmul8x16_vis:
case CODE_FOR_fmul8x16au_vis:
case CODE_FOR_fmul8x16al_vis:
case SPARC_BUILTIN_FMUL8X16:
case SPARC_BUILTIN_FMUL8X16AU:
case SPARC_BUILTIN_FMUL8X16AL:
arg0 = args[0];
arg1 = args[1];
STRIP_NOPS (arg0);
......@@ -10615,12 +10787,12 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
{
tree inner_type = TREE_TYPE (rtype);
tree *n_elts = XALLOCAVEC (tree, VECTOR_CST_NELTS (arg0));
sparc_handle_vis_mul8x16 (n_elts, icode, inner_type, arg0, arg1);
sparc_handle_vis_mul8x16 (n_elts, code, inner_type, arg0, arg1);
return build_vector (rtype, n_elts);
}
break;
case CODE_FOR_fpmerge_vis:
case SPARC_BUILTIN_FPMERGE:
arg0 = args[0];
arg1 = args[1];
STRIP_NOPS (arg0);
......@@ -10640,13 +10812,19 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
}
break;
case CODE_FOR_pdist_vis:
case SPARC_BUILTIN_PDIST:
case SPARC_BUILTIN_PDISTN:
arg0 = args[0];
arg1 = args[1];
arg2 = args[2];
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
STRIP_NOPS (arg2);
if (code == SPARC_BUILTIN_PDIST)
{
arg2 = args[2];
STRIP_NOPS (arg2);
}
else
arg2 = integer_zero_node;
if (TREE_CODE (arg0) == VECTOR_CST
&& TREE_CODE (arg1) == VECTOR_CST
......@@ -12325,9 +12503,106 @@ sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
return true;
}
static enum machine_mode sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED)
/* Implement TARGET_CSTORE_MODE. */
static enum machine_mode
sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED)
{
return (TARGET_ARCH64 ? DImode : SImode);
}
/* Return the compound expression made of T1 and T2. */
static inline tree
compound_expr (tree t1, tree t2)
{
return build2 (COMPOUND_EXPR, void_type_node, t1, t2);
}
/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV hook. */
static void
sparc_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
{
if (!TARGET_FPU)
return;
const unsigned HOST_WIDE_INT accrued_exception_mask = 0x1f << 5;
const unsigned HOST_WIDE_INT trap_enable_mask = 0x1f << 23;
/* We generate the equivalent of feholdexcept (&fenv_var):
unsigned int fenv_var;
__builtin_store_fsr (&fenv_var);
unsigned int tmp1_var;
tmp1_var = fenv_var & ~(accrued_exception_mask | trap_enable_mask);
__builtin_load_fsr (&tmp1_var); */
tree fenv_var = create_tmp_var (unsigned_type_node, NULL);
mark_addressable (fenv_var);
tree fenv_addr = build_fold_addr_expr (fenv_var);
tree stfsr = sparc_builtins[SPARC_BUILTIN_STFSR];
tree hold_stfsr = build_call_expr (stfsr, 1, fenv_addr);
tree tmp1_var = create_tmp_var (unsigned_type_node, NULL);
mark_addressable (tmp1_var);
tree masked_fenv_var
= build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var,
build_int_cst (unsigned_type_node,
~(accrued_exception_mask | trap_enable_mask)));
tree hold_mask
= build2 (MODIFY_EXPR, void_type_node, tmp1_var, masked_fenv_var);
tree tmp1_addr = build_fold_addr_expr (tmp1_var);
tree ldfsr = sparc_builtins[SPARC_BUILTIN_LDFSR];
tree hold_ldfsr = build_call_expr (ldfsr, 1, tmp1_addr);
*hold = compound_expr (compound_expr (hold_stfsr, hold_mask), hold_ldfsr);
/* We reload the value of tmp1_var to clear the exceptions:
__builtin_load_fsr (&tmp1_var); */
*clear = build_call_expr (ldfsr, 1, tmp1_addr);
/* We generate the equivalent of feupdateenv (&fenv_var):
unsigned int tmp2_var;
__builtin_store_fsr (&tmp2_var);
__builtin_load_fsr (&fenv_var);
if (SPARC_LOW_FE_EXCEPT_VALUES)
tmp2_var >>= 5;
__atomic_feraiseexcept ((int) tmp2_var); */
tree tmp2_var = create_tmp_var (unsigned_type_node, NULL);
mark_addressable (tmp2_var);
tree tmp3_addr = build_fold_addr_expr (tmp2_var);
tree update_stfsr = build_call_expr (stfsr, 1, tmp3_addr);
tree update_ldfsr = build_call_expr (ldfsr, 1, fenv_addr);
tree atomic_feraiseexcept
= builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
tree update_call
= build_call_expr (atomic_feraiseexcept, 1,
fold_convert (integer_type_node, tmp2_var));
if (SPARC_LOW_FE_EXCEPT_VALUES)
{
tree shifted_tmp2_var
= build2 (RSHIFT_EXPR, unsigned_type_node, tmp2_var,
build_int_cst (unsigned_type_node, 5));
tree update_shift
= build2 (MODIFY_EXPR, void_type_node, tmp2_var, shifted_tmp2_var);
update_call = compound_expr (update_shift, update_call);
}
*update
= compound_expr (compound_expr (update_stfsr, update_ldfsr), update_call);
}
#include "gt-sparc.h"
......@@ -1777,3 +1777,6 @@ extern int sparc_indent_opcode;
#ifndef SUBTARGET_DEFAULT_MEMORY_MODEL
#define SUBTARGET_DEFAULT_MEMORY_MODEL SMM_DEFAULT
#endif
/* Define this to 1 if the FE_EXCEPT values defined in fenv.h start at 1. */
#define SPARC_LOW_FE_EXCEPT_VALUES 0
......@@ -96,13 +96,19 @@
(define_c_enum "unspecv" [
UNSPECV_BLOCKAGE
UNSPECV_PROBE_STACK_RANGE
UNSPECV_FLUSHW
UNSPECV_FLUSH
UNSPECV_SAVEW
UNSPECV_CAS
UNSPECV_SWAP
UNSPECV_FLUSH
UNSPECV_LDSTUB
UNSPECV_PROBE_STACK_RANGE
UNSPECV_SWAP
UNSPECV_CAS
UNSPECV_LDFSR
UNSPECV_STFSR
])
(define_constants
......@@ -6783,22 +6789,26 @@
;; Special pattern for the FLUSH instruction.
; We do SImode and DImode versions of this to quiet down genrecog's complaints
; of the define_insn otherwise missing a mode. We make "flush", aka
; gen_flush, the default one since sparc_initialize_trampoline uses
; it on SImode mem values.
(define_insn "flush"
[(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
(define_insn "flush<P:mode>"
[(unspec_volatile [(match_operand:P 0 "memory_operand" "m")] UNSPECV_FLUSH)]
""
{ return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
[(set_attr "type" "iflush")])
(define_insn "flushdi"
[(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
""
{ return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
[(set_attr "type" "iflush")])
;; Special insns to load and store the 32-bit FP Status Register.
(define_insn "ldfsr"
[(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_LDFSR)]
"TARGET_FPU"
"ld\t%0, %%fsr"
[(set_attr "type" "load")])
(define_insn "stfsr"
[(set (match_operand:SI 0 "memory_operand" "=m")
(unspec_volatile:SI [(const_int 0)] UNSPECV_STFSR))]
"TARGET_FPU"
"st\t%%fsr, %0"
[(set_attr "type" "store")])
;; Find first set instructions.
......
2013-12-06 Eric Botcazou <ebotcazou@adacore.com>
* gcc.target/sparc/pdistn.c: New test.
* gcc.target/sparc/pdistn-2.c: Likewise.
2013-12-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/59058
......
/* { dg-do compile } */
/* { dg-options "-mcpu=ultrasparc -mvis3 -O1 -fdump-tree-optimized" } */
typedef unsigned char vec8 __attribute__((vector_size(8)));
#define _(A) (unsigned char)A
long foo () {
vec8 a = { _(1), _(2), _(3), _(4), _(5), _(6), _(7), _(255) };
vec8 b = { _(2), _(4), _(8), _(16), _(32), _(64), _(128), _(8) };
return __builtin_vis_pdistn (a, b);
}
/* { dg-final { scan-assembler-not "pdistn\t%" } } */
/* { dg-final { scan-tree-dump "return 473" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=ultrasparc -mvis3" } */
typedef unsigned char vec8 __attribute__((vector_size(8)));
long foo (vec8 a, vec8 b) {
return __builtin_vis_pdistn (a, b);
}
/* { dg-final { scan-assembler-times "pdistn\t%" 1 } } */
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