Commit 7a12ea32 by Monk Chiang Committed by Chung-Ju Wu

[NDS32] Rewrite infrastructure for intrinsic.

gcc/
	* config/nds32/nds32-intrinsic.c
	(nds32_expand_builtin_null_ftype_reg): Delete.
	(nds32_expand_builtin_reg_ftype_imm): Ditto.
	(nds32_expand_builtin_null_ftype_reg_imm): Ditto.
	(nds32_read_argument): New.
	(nds32_legitimize_target): Ditto.
	(nds32_legitimize_argument): Ditto.
	(nds32_check_constant_argument): Ditto.
	(nds32_expand_unop_builtin): Ditto.
	(nds32_expand_unopimm_builtin): Ditto.
	(nds32_expand_binop_builtin): Ditto.
	(nds32_builtin_decl_impl): Ditto.
	(builtin_description): Ditto.
	(nds32_expand_builtin_impl): Rewrite with new infrastructure.
	(nds32_init_builtins_impl): Ditto.
	* config/nds32/nds32.c (TARGET_BUILTIN_DECL): Define.
	(nds32_builtin_decl): New.
	* config/nds32/nds32.h (nds32_builtins): Add NDS32_BUILTIN_COUNT.
	* config/nds32/nds32-protos.h (nds32_builtin_decl_impl): Declare.

Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>
Co-Authored-By: Kito Cheng <kito.cheng@gmail.com>

From-SVN: r258211
parent c8bd326c
2018-03-03 Monk Chiang <sh.chiang04@gmail.com>
Kito Cheng <kito.cheng@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32-intrinsic.c
(nds32_expand_builtin_null_ftype_reg): Delete.
(nds32_expand_builtin_reg_ftype_imm): Ditto.
(nds32_expand_builtin_null_ftype_reg_imm): Ditto.
(nds32_read_argument): New.
(nds32_legitimize_target): Ditto.
(nds32_legitimize_argument): Ditto.
(nds32_check_constant_argument): Ditto.
(nds32_expand_unop_builtin): Ditto.
(nds32_expand_unopimm_builtin): Ditto.
(nds32_expand_binop_builtin): Ditto.
(nds32_builtin_decl_impl): Ditto.
(builtin_description): Ditto.
(nds32_expand_builtin_impl): Rewrite with new infrastructure.
(nds32_init_builtins_impl): Ditto.
* config/nds32/nds32.c (TARGET_BUILTIN_DECL): Define.
(nds32_builtin_decl): New.
* config/nds32/nds32.h (nds32_builtins): Add NDS32_BUILTIN_COUNT.
* config/nds32/nds32-protos.h (nds32_builtin_decl_impl): Declare.
2018-03-02 Jeff Law <law@redhat.com> 2018-03-02 Jeff Law <law@redhat.com>
* reorg.c (stop_search_p): Handle DEBUG_INSN. * reorg.c (stop_search_p): Handle DEBUG_INSN.
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include "backend.h" #include "backend.h"
#include "target.h" #include "target.h"
#include "rtl.h" #include "rtl.h"
#include "memmodel.h"
#include "emit-rtl.h"
#include "tree.h" #include "tree.h"
#include "memmodel.h" #include "memmodel.h"
#include "optabs.h" /* For GEN_FCN. */ #include "optabs.h" /* For GEN_FCN. */
...@@ -35,202 +37,337 @@ ...@@ -35,202 +37,337 @@
#include "stor-layout.h" #include "stor-layout.h"
#include "expr.h" #include "expr.h"
#include "langhooks.h" /* For add_builtin_function(). */ #include "langhooks.h" /* For add_builtin_function(). */
#include "recog.h"
#include "explow.h"
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* Function to expand builtin function for /* Read the requested argument from the EXP given by INDEX.
'[(unspec_volatile [(reg)])]'. */ Return the value as an rtx. */
static rtx static rtx
nds32_expand_builtin_null_ftype_reg (enum insn_code icode, nds32_read_argument (tree exp, unsigned int index)
tree exp, rtx target)
{ {
/* Mapping: return expand_normal (CALL_EXPR_ARG (exp, index));
ops[0] <--> value0 <--> arg0 */ }
struct expand_operand ops[1];
tree arg0;
rtx value0;
/* Grab the incoming arguments and extract its rtx. */ /* Return a legitimate rtx for instruction ICODE's return value. Use TARGET
arg0 = CALL_EXPR_ARG (exp, 0); if it's not null, has the right mode, and satisfies operand 0's
value0 = expand_normal (arg0); predicate. */
static rtx
nds32_legitimize_target (enum insn_code icode, rtx target)
{
enum machine_mode mode = insn_data[icode].operand[0].mode;
if (! target
|| GET_MODE (target) != mode
|| ! (*insn_data[icode].operand[0].predicate) (target, mode))
return gen_reg_rtx (mode);
else
return target;
}
/* Create operands. */ /* Given that ARG is being passed as operand OPNUM to instruction ICODE,
create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0))); check whether ARG satisfies the operand's constraints. If it doesn't,
copy ARG to a temporary register and return that. Otherwise return ARG
itself. */
static rtx
nds32_legitimize_argument (enum insn_code icode, int opnum, rtx arg)
{
enum machine_mode mode = insn_data[icode].operand[opnum].mode;
/* Emit new instruction. */ if ((*insn_data[icode].operand[opnum].predicate) (arg, mode))
if (!maybe_expand_insn (icode, 1, ops)) return arg;
error ("invalid argument to built-in function"); else if (VECTOR_MODE_P (mode) && CONST_INT_P (arg))
{
/* Handle CONST_INT covert to CONST_VECTOR. */
int nunits = GET_MODE_NUNITS (mode);
int i, shift = 0;
rtvec v = rtvec_alloc (nunits);
int val = INTVAL (arg);
enum machine_mode val_mode = (mode == V4QImode) ? QImode : HImode;
int shift_acc = (val_mode == QImode) ? 8 : 16;
int mask = (val_mode == QImode) ? 0xff : 0xffff;
int tmp_val = val;
if (TARGET_BIG_ENDIAN)
for (i = 0; i < nunits; i++)
{
tmp_val = (val >> shift) & mask;
RTVEC_ELT (v, nunits - i - 1) = gen_int_mode (tmp_val, val_mode);
shift += shift_acc;
}
else
for (i = 0; i < nunits; i++)
{
tmp_val = (val >> shift) & mask;
RTVEC_ELT (v, i) = gen_int_mode (tmp_val, val_mode);
shift += shift_acc;
}
return copy_to_mode_reg (mode, gen_rtx_CONST_VECTOR (mode, v));
}
else
{
rtx tmp_rtx = gen_reg_rtx (mode);
convert_move (tmp_rtx, arg, false);
return tmp_rtx;
}
}
return target; /* Return true if OPVAL can be used for operand OPNUM of instruction ICODE.
The instruction should require a constant operand of some sort. The
function prints an error if OPVAL is not valid. */
static int
nds32_check_constant_argument (enum insn_code icode, int opnum, rtx opval,
const char *name)
{
if (GET_CODE (opval) != CONST_INT)
{
error ("invalid argument to built-in function %s", name);
return false;
}
if (! (*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode))
{
error ("constant argument out of range for %s", name);
return false;
}
return true;
} }
/* Function to expand builtin function for /* Expand builtins that take one operand. */
'[(set (reg) (unspec_volatile [(imm)]))]'. */
static rtx static rtx
nds32_expand_builtin_reg_ftype_imm (enum insn_code icode, nds32_expand_unop_builtin (enum insn_code icode, tree exp, rtx target,
tree exp, rtx target) bool return_p)
{ {
/* Mapping: rtx pat;
ops[0] <--> target <--> exp rtx op0 = nds32_read_argument (exp, 0);
ops[1] <--> value0 <--> arg0 */ int op0_num = return_p ? 1 : 0;
struct expand_operand ops[2];
tree arg0; if (return_p)
rtx value0; target = nds32_legitimize_target (icode, target);
/* Grab the incoming arguments and extract its rtx. */ op0 = nds32_legitimize_argument (icode, op0_num, op0);
arg0 = CALL_EXPR_ARG (exp, 0);
value0 = expand_normal (arg0);
/* Create operands. */ /* Emit and return the new instruction. */
create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp))); if (return_p)
create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0))); pat = GEN_FCN (icode) (target, op0);
else
pat = GEN_FCN (icode) (op0);
/* Emit new instruction. */ if (! pat)
if (!maybe_expand_insn (icode, 2, ops)) return NULL_RTX;
error ("invalid argument to built-in function");
emit_insn (pat);
return target; return target;
} }
/* Function to expand builtin function for /* Expand builtins that take one operands and the first is immediate. */
'[(unspec_volatile [(reg) (imm)])]' pattern. */
static rtx static rtx
nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode, nds32_expand_unopimm_builtin (enum insn_code icode, tree exp, rtx target,
tree exp, rtx target) bool return_p, const char *name)
{ {
/* Mapping: rtx pat;
ops[0] <--> value0 <--> arg0 rtx op0 = nds32_read_argument (exp, 0);
ops[1] <--> value1 <--> arg1 */ int op0_num = return_p ? 1 : 0;
struct expand_operand ops[2];
tree arg0, arg1; if (return_p)
rtx value0, value1; target = nds32_legitimize_target (icode, target);
/* Grab the incoming arguments and extract its rtx. */ if (!nds32_check_constant_argument (icode, op0_num, op0, name))
arg0 = CALL_EXPR_ARG (exp, 0); return NULL_RTX;
arg1 = CALL_EXPR_ARG (exp, 1);
value0 = expand_normal (arg0); op0 = nds32_legitimize_argument (icode, op0_num, op0);
value1 = expand_normal (arg1);
/* Emit and return the new instruction. */
/* Create operands. */ if (return_p)
create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0))); pat = GEN_FCN (icode) (target, op0);
create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1))); else
pat = GEN_FCN (icode) (op0);
/* Emit new instruction. */
if (!maybe_expand_insn (icode, 2, ops))
error ("invalid argument to built-in function");
if (! pat)
return NULL_RTX;
emit_insn (pat);
return target; return target;
} }
/* ------------------------------------------------------------------------ */ /* Expand builtins that take two operands. */
static rtx
void nds32_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
nds32_init_builtins_impl (void) bool return_p)
{ {
tree pointer_type_node = build_pointer_type (integer_type_node); rtx pat;
rtx op0 = nds32_read_argument (exp, 0);
rtx op1 = nds32_read_argument (exp, 1);
int op0_num = return_p ? 1 : 0;
int op1_num = return_p ? 2 : 1;
tree void_ftype_void = build_function_type (void_type_node, if (return_p)
void_list_node); target = nds32_legitimize_target (icode, target);
tree void_ftype_pint = build_function_type_list (void_type_node, op0 = nds32_legitimize_argument (icode, op0_num, op0);
pointer_type_node, op1 = nds32_legitimize_argument (icode, op1_num, op1);
NULL_TREE);
tree int_ftype_int = build_function_type_list (integer_type_node, /* Emit and return the new instruction. */
integer_type_node, if (return_p)
NULL_TREE); pat = GEN_FCN (icode) (target, op0, op1);
else
pat = GEN_FCN (icode) (op0, op1);
tree void_ftype_int_int = build_function_type_list (void_type_node, if (! pat)
integer_type_node, return NULL_RTX;
integer_type_node,
NULL_TREE);
/* Cache. */ emit_insn (pat);
add_builtin_function ("__builtin_nds32_isync", void_ftype_pint, return target;
NDS32_BUILTIN_ISYNC, }
BUILT_IN_MD, NULL, NULL_TREE);
add_builtin_function ("__builtin_nds32_isb", void_ftype_void,
NDS32_BUILTIN_ISB,
BUILT_IN_MD, NULL, NULL_TREE);
/* Register Transfer. */ struct builtin_description
add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int, {
NDS32_BUILTIN_MFSR, const enum insn_code icode;
BUILT_IN_MD, NULL, NULL_TREE); const char *name;
add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int, enum nds32_builtins code;
NDS32_BUILTIN_MFUSR, bool return_p;
BUILT_IN_MD, NULL, NULL_TREE); };
add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int,
NDS32_BUILTIN_MTSR, #define NDS32_BUILTIN(code, string, builtin) \
BUILT_IN_MD, NULL, NULL_TREE); { CODE_FOR_##code, "__nds32__" string, \
add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int, NDS32_BUILTIN_##builtin, true },
NDS32_BUILTIN_MTUSR,
BUILT_IN_MD, NULL, NULL_TREE); #define NDS32_NO_TARGET_BUILTIN(code, string, builtin) \
{ CODE_FOR_##code, "__nds32__" string, \
NDS32_BUILTIN_##builtin, false },
/* Intrinsics that take just one argument. */
static struct builtin_description bdesc_1arg[] =
{
NDS32_NO_TARGET_BUILTIN(unspec_volatile_isync, "isync", ISYNC)
};
/* Interrupt. */ /* Intrinsics that take just one argument. and the argument is immediate. */
add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void, static struct builtin_description bdesc_1argimm[] =
NDS32_BUILTIN_SETGIE_EN, {
BUILT_IN_MD, NULL, NULL_TREE); NDS32_BUILTIN(unspec_volatile_mfsr, "mfsr", MFSR)
add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void, NDS32_BUILTIN(unspec_volatile_mfusr, "mfsr", MFUSR)
NDS32_BUILTIN_SETGIE_DIS, };
BUILT_IN_MD, NULL, NULL_TREE);
}
/* Intrinsics that take two arguments. */
static struct builtin_description bdesc_2arg[] =
{
NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtsr, "mtsr", MTSR)
NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtusr, "mtusr", MTUSR)
};
rtx rtx
nds32_expand_builtin_impl (tree exp, nds32_expand_builtin_impl (tree exp,
rtx target, rtx target,
rtx subtarget ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED) int ignore ATTRIBUTE_UNUSED)
{ {
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
unsigned i;
struct builtin_description *d;
int fcode = DECL_FUNCTION_CODE (fndecl); /* Since there are no result and operands, we can simply emit this rtx. */
switch (fcode) switch (fcode)
{ {
/* Cache. */
case NDS32_BUILTIN_ISYNC:
return nds32_expand_builtin_null_ftype_reg
(CODE_FOR_unspec_volatile_isync, exp, target);
case NDS32_BUILTIN_ISB: case NDS32_BUILTIN_ISB:
/* Since there are no result and operands for isb instruciton,
we can simply emit this rtx. */
emit_insn (gen_unspec_volatile_isb ()); emit_insn (gen_unspec_volatile_isb ());
return target; return target;
/* Register Transfer. */
case NDS32_BUILTIN_MFSR:
return nds32_expand_builtin_reg_ftype_imm
(CODE_FOR_unspec_volatile_mfsr, exp, target);
case NDS32_BUILTIN_MFUSR:
return nds32_expand_builtin_reg_ftype_imm
(CODE_FOR_unspec_volatile_mfusr, exp, target);
case NDS32_BUILTIN_MTSR:
return nds32_expand_builtin_null_ftype_reg_imm
(CODE_FOR_unspec_volatile_mtsr, exp, target);
case NDS32_BUILTIN_MTUSR:
return nds32_expand_builtin_null_ftype_reg_imm
(CODE_FOR_unspec_volatile_mtusr, exp, target);
/* Interrupt. */
case NDS32_BUILTIN_SETGIE_EN: case NDS32_BUILTIN_SETGIE_EN:
/* Since there are no result and operands for setgie.e instruciton,
we can simply emit this rtx. */
emit_insn (gen_unspec_volatile_setgie_en ()); emit_insn (gen_unspec_volatile_setgie_en ());
return target; return target;
case NDS32_BUILTIN_SETGIE_DIS: case NDS32_BUILTIN_SETGIE_DIS:
/* Since there are no result and operands for setgie.d instruciton,
we can simply emit this rtx. */
emit_insn (gen_unspec_volatile_setgie_dis ()); emit_insn (gen_unspec_volatile_setgie_dis ());
return target; return target;
default: default:
gcc_unreachable (); break;
} }
/* Expand groups of builtins. */
for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
if (d->code == fcode)
return nds32_expand_unop_builtin (d->icode, exp, target, d->return_p);
for (i = 0, d = bdesc_1argimm; i < ARRAY_SIZE (bdesc_1argimm); i++, d++)
if (d->code == fcode)
return nds32_expand_unopimm_builtin (d->icode, exp, target,
d->return_p, d->name);
for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
if (d->code == fcode)
return nds32_expand_binop_builtin (d->icode, exp, target, d->return_p);
return NULL_RTX; return NULL_RTX;
} }
/* ------------------------------------------------------------------------ */ static GTY(()) tree nds32_builtin_decls[NDS32_BUILTIN_COUNT];
/* Return the NDS32 builtin for CODE. */
tree
nds32_builtin_decl_impl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
{
if (code >= NDS32_BUILTIN_COUNT)
return error_mark_node;
return nds32_builtin_decls[code];
}
void
nds32_init_builtins_impl (void)
{
#define ADD_NDS32_BUILTIN0(NAME, RET_TYPE, CODE) \
nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \
add_builtin_function ("__builtin_nds32_" NAME, \
build_function_type_list (RET_TYPE##_type_node, \
NULL_TREE), \
NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
#define ADD_NDS32_BUILTIN1(NAME, RET_TYPE, ARG_TYPE, CODE) \
nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \
add_builtin_function ("__builtin_nds32_" NAME, \
build_function_type_list (RET_TYPE##_type_node, \
ARG_TYPE##_type_node, \
NULL_TREE), \
NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
#define ADD_NDS32_BUILTIN2(NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2, CODE) \
nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \
add_builtin_function ("__builtin_nds32_" NAME, \
build_function_type_list (RET_TYPE##_type_node, \
ARG_TYPE1##_type_node,\
ARG_TYPE2##_type_node,\
NULL_TREE), \
NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
#define ADD_NDS32_BUILTIN3(NAME, RET_TYPE, \
ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, CODE) \
nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \
add_builtin_function ("__builtin_nds32_" NAME, \
build_function_type_list (RET_TYPE##_type_node, \
ARG_TYPE1##_type_node,\
ARG_TYPE2##_type_node,\
ARG_TYPE3##_type_node,\
NULL_TREE), \
NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
/* Looking for return type and argument can be found in tree.h file. */
tree ptr_uint_type_node = build_pointer_type (unsigned_type_node);
/* Cache. */
ADD_NDS32_BUILTIN1 ("isync", void, ptr_uint, ISYNC);
ADD_NDS32_BUILTIN0 ("isb", void, ISB);
/* Register Transfer. */
ADD_NDS32_BUILTIN1 ("mfsr", unsigned, integer, MFSR);
ADD_NDS32_BUILTIN1 ("mfusr", unsigned, integer, MFUSR);
ADD_NDS32_BUILTIN2 ("mtsr", void, unsigned, integer, MTSR);
ADD_NDS32_BUILTIN2 ("mtusr", void, unsigned, integer, MTUSR);
/* Interrupt. */
ADD_NDS32_BUILTIN0 ("setgie_en", void, SETGIE_EN);
ADD_NDS32_BUILTIN0 ("setgie_dis", void, SETGIE_DIS);
}
...@@ -125,6 +125,7 @@ extern int nds32_target_alignment (rtx_insn *); ...@@ -125,6 +125,7 @@ extern int nds32_target_alignment (rtx_insn *);
extern void nds32_init_builtins_impl (void); extern void nds32_init_builtins_impl (void);
extern rtx nds32_expand_builtin_impl (tree, rtx, rtx, extern rtx nds32_expand_builtin_impl (tree, rtx, rtx,
machine_mode, int); machine_mode, int);
extern tree nds32_builtin_decl_impl (unsigned, bool);
/* Auxiliary functions for ISR implementation. */ /* Auxiliary functions for ISR implementation. */
......
...@@ -2728,6 +2728,13 @@ nds32_init_builtins (void) ...@@ -2728,6 +2728,13 @@ nds32_init_builtins (void)
nds32_init_builtins_impl (); nds32_init_builtins_impl ();
} }
static tree
nds32_builtin_decl (unsigned code, bool initialize_p)
{
/* Implement in nds32-intrinsic.c. */
return nds32_builtin_decl_impl (code, initialize_p);
}
static rtx static rtx
nds32_expand_builtin (tree exp, nds32_expand_builtin (tree exp,
rtx target, rtx target,
...@@ -3825,6 +3832,9 @@ nds32_target_alignment (rtx_insn *label) ...@@ -3825,6 +3832,9 @@ nds32_target_alignment (rtx_insn *label)
#undef TARGET_INIT_BUILTINS #undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS nds32_init_builtins #define TARGET_INIT_BUILTINS nds32_init_builtins
#undef TARGET_BUILTIN_DECL
#define TARGET_BUILTIN_DECL nds32_builtin_decl
#undef TARGET_EXPAND_BUILTIN #undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN nds32_expand_builtin #define TARGET_EXPAND_BUILTIN nds32_expand_builtin
......
...@@ -345,7 +345,8 @@ enum nds32_builtins ...@@ -345,7 +345,8 @@ enum nds32_builtins
NDS32_BUILTIN_MTSR, NDS32_BUILTIN_MTSR,
NDS32_BUILTIN_MTUSR, NDS32_BUILTIN_MTUSR,
NDS32_BUILTIN_SETGIE_EN, NDS32_BUILTIN_SETGIE_EN,
NDS32_BUILTIN_SETGIE_DIS NDS32_BUILTIN_SETGIE_DIS,
NDS32_BUILTIN_COUNT
}; };
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
......
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