Commit b99ce2a8 by Richard Sandiford Committed by Richard Sandiford

mips.c (mips_prepare_builtin_arg): Replace icode and opno arguments with an expand_operand.

gcc/
	* config/mips/mips.c (mips_prepare_builtin_arg): Replace icode and
	opno arguments with an expand_operand.  Use create_input_operand.
	(mips_prepare_builtin_target): Delete.
	(mips_expand_builtin_insn, mips_expand_builtin_compare_1): New
	functions.
	(mips_expand_builtin_direct): Use create_output_operand and
	mips_expand_builtin_insn.  Update call to mips_prepare_builtin_arg.
	(mips_expand_builtin_movtf): Likewise.  Use mips_expand_fp_comparison.
	(mips_expand_builtin_compare): Use mips_expand_fp_comparison.

From-SVN: r171571
parent 5092eb96
2011-03-27 Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips.c (mips_prepare_builtin_arg): Replace icode and
opno arguments with an expand_operand. Use create_input_operand.
(mips_prepare_builtin_target): Delete.
(mips_expand_builtin_insn, mips_expand_builtin_compare_1): New
functions.
(mips_expand_builtin_direct): Use create_output_operand and
mips_expand_builtin_insn. Update call to mips_prepare_builtin_arg.
(mips_expand_builtin_movtf): Likewise. Use mips_expand_fp_comparison.
(mips_expand_builtin_compare): Use mips_expand_fp_comparison.
2011-03-27 Ira Rosen <ira.rosen@linaro.org> 2011-03-27 Ira Rosen <ira.rosen@linaro.org>
* config/arm/arm.c (arm_autovectorize_vector_sizes): New * config/arm/arm.c (arm_autovectorize_vector_sizes): New
......
...@@ -13184,56 +13184,64 @@ mips_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) ...@@ -13184,56 +13184,64 @@ mips_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
return mips_builtin_decls[code]; return mips_builtin_decls[code];
} }
/* Take argument ARGNO from EXP's argument list and convert it into a /* Take argument ARGNO from EXP's argument list and convert it into
form suitable for input operand OPNO of instruction ICODE. Return the an expand operand. Store the operand in *OP. */
value. */
static rtx static void
mips_prepare_builtin_arg (enum insn_code icode, mips_prepare_builtin_arg (struct expand_operand *op, tree exp,
unsigned int opno, tree exp, unsigned int argno) unsigned int argno)
{ {
tree arg; tree arg;
rtx value; rtx value;
enum machine_mode mode;
arg = CALL_EXPR_ARG (exp, argno); arg = CALL_EXPR_ARG (exp, argno);
value = expand_normal (arg); value = expand_normal (arg);
mode = insn_data[icode].operand[opno].mode; create_input_operand (op, value, TYPE_MODE (TREE_TYPE (arg)));
if (!insn_data[icode].operand[opno].predicate (value, mode)) }
{
/* We need to get the mode from ARG for two reasons:
- to cope with address operands, where MODE is the mode of the /* Expand instruction ICODE as part of a built-in function sequence.
memory, rather than of VALUE itself. Use the first NOPS elements of OPS as the instruction's operands.
HAS_TARGET_P is true if operand 0 is a target; it is false if the
instruction has no target.
- to cope with special predicates like pmode_register_operand, Return the target rtx if HAS_TARGET_P, otherwise return const0_rtx. */
where MODE is VOIDmode. */
value = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (arg)), value);
/* Check the predicate again. */ static rtx
if (!insn_data[icode].operand[opno].predicate (value, mode)) mips_expand_builtin_insn (enum insn_code icode, unsigned int nops,
{ struct expand_operand *ops, bool has_target_p)
error ("invalid argument to built-in function"); {
return const0_rtx; if (!maybe_expand_insn (icode, nops, ops))
} {
error ("invalid argument to built-in function");
return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
} }
return has_target_p ? ops[0].value : const0_rtx;
return value;
} }
/* Return an rtx suitable for output operand OP of instruction ICODE. /* Expand a floating-point comparison for built-in function call EXP.
If TARGET is non-null, try to use it where possible. */ The first NARGS arguments are the values to be compared. ICODE is
the .md pattern that does the comparison and COND is the condition
that is being tested. Return an rtx for the result. */
static rtx static rtx
mips_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target) mips_expand_builtin_compare_1 (enum insn_code icode,
enum mips_fp_condition cond,
tree exp, int nargs)
{ {
enum machine_mode mode; struct expand_operand ops[MAX_RECOG_OPERANDS];
int opno, argno;
mode = insn_data[icode].operand[op].mode; /* The instruction should have a target operand, an operand for each
if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode)) argument, and an operand for COND. */
target = gen_reg_rtx (mode); gcc_assert (nargs + 2 == insn_data[(int) icode].n_operands);
return target; opno = 0;
create_output_operand (&ops[opno++], NULL_RTX,
insn_data[(int) icode].operand[0].mode);
for (argno = 0; argno < nargs; argno++)
mips_prepare_builtin_arg (&ops[opno++], exp, argno);
create_integer_operand (&ops[opno++], (int) cond);
return mips_expand_builtin_insn (icode, opno, ops, true);
} }
/* Expand a MIPS_BUILTIN_DIRECT or MIPS_BUILTIN_DIRECT_NO_TARGET function; /* Expand a MIPS_BUILTIN_DIRECT or MIPS_BUILTIN_DIRECT_NO_TARGET function;
...@@ -13245,44 +13253,23 @@ static rtx ...@@ -13245,44 +13253,23 @@ static rtx
mips_expand_builtin_direct (enum insn_code icode, rtx target, tree exp, mips_expand_builtin_direct (enum insn_code icode, rtx target, tree exp,
bool has_target_p) bool has_target_p)
{ {
rtx ops[MAX_RECOG_OPERANDS]; struct expand_operand ops[MAX_RECOG_OPERANDS];
int opno, argno; int opno, argno;
/* Map any target to operand 0. */ /* Map any target to operand 0. */
opno = 0; opno = 0;
if (has_target_p) if (has_target_p)
{ create_output_operand (&ops[opno++], target, TYPE_MODE (TREE_TYPE (exp)));
target = mips_prepare_builtin_target (icode, opno, target);
ops[opno] = target;
opno++;
}
/* Map the arguments to the other operands. The n_operands value /* Map the arguments to the other operands. The n_operands value
for an expander includes match_dups and match_scratches as well as for an expander includes match_dups and match_scratches as well as
match_operands, so n_operands is only an upper bound on the number match_operands, so n_operands is only an upper bound on the number
of arguments to the expander function. */ of arguments to the expander function. */
gcc_assert (opno + call_expr_nargs (exp) <= insn_data[icode].n_operands); gcc_assert (opno + call_expr_nargs (exp) <= insn_data[icode].n_operands);
for (argno = 0; argno < call_expr_nargs (exp); argno++, opno++) for (argno = 0; argno < call_expr_nargs (exp); argno++)
ops[opno] = mips_prepare_builtin_arg (icode, opno, exp, argno); mips_prepare_builtin_arg (&ops[opno++], exp, argno);
switch (opno)
{
case 2:
emit_insn (GEN_FCN (icode) (ops[0], ops[1]));
break;
case 3:
emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2]));
break;
case 4:
emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]));
break;
default: return mips_expand_builtin_insn (icode, opno, ops, has_target_p);
gcc_unreachable ();
}
return target;
} }
/* Expand a __builtin_mips_movt_*_ps or __builtin_mips_movf_*_ps /* Expand a __builtin_mips_movt_*_ps or __builtin_mips_movf_*_ps
...@@ -13296,27 +13283,24 @@ mips_expand_builtin_movtf (enum mips_builtin_type type, ...@@ -13296,27 +13283,24 @@ mips_expand_builtin_movtf (enum mips_builtin_type type,
enum insn_code icode, enum mips_fp_condition cond, enum insn_code icode, enum mips_fp_condition cond,
rtx target, tree exp) rtx target, tree exp)
{ {
rtx cmp_result, op0, op1; struct expand_operand ops[4];
rtx cmp_result;
cmp_result = mips_prepare_builtin_target (icode, 0, 0);
op0 = mips_prepare_builtin_arg (icode, 1, exp, 0);
op1 = mips_prepare_builtin_arg (icode, 2, exp, 1);
emit_insn (GEN_FCN (icode) (cmp_result, op0, op1, GEN_INT (cond)));
icode = CODE_FOR_mips_cond_move_tf_ps; cmp_result = mips_expand_builtin_compare_1 (icode, cond, exp, 2);
target = mips_prepare_builtin_target (icode, 0, target); create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
if (type == MIPS_BUILTIN_MOVT) if (type == MIPS_BUILTIN_MOVT)
{ {
op1 = mips_prepare_builtin_arg (icode, 2, exp, 2); mips_prepare_builtin_arg (&ops[2], exp, 2);
op0 = mips_prepare_builtin_arg (icode, 1, exp, 3); mips_prepare_builtin_arg (&ops[1], exp, 3);
} }
else else
{ {
op0 = mips_prepare_builtin_arg (icode, 1, exp, 2); mips_prepare_builtin_arg (&ops[1], exp, 2);
op1 = mips_prepare_builtin_arg (icode, 2, exp, 3); mips_prepare_builtin_arg (&ops[2], exp, 3);
} }
emit_insn (gen_mips_cond_move_tf_ps (target, op0, op1, cmp_result)); create_fixed_operand (&ops[3], cmp_result);
return target; return mips_expand_builtin_insn (CODE_FOR_mips_cond_move_tf_ps,
4, ops, true);
} }
/* Move VALUE_IF_TRUE into TARGET if CONDITION is true; move VALUE_IF_FALSE /* Move VALUE_IF_TRUE into TARGET if CONDITION is true; move VALUE_IF_FALSE
...@@ -13357,36 +13341,12 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type, ...@@ -13357,36 +13341,12 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
enum insn_code icode, enum mips_fp_condition cond, enum insn_code icode, enum mips_fp_condition cond,
rtx target, tree exp) rtx target, tree exp)
{ {
rtx offset, condition, cmp_result, args[MAX_RECOG_OPERANDS]; rtx offset, condition, cmp_result;
int argno;
if (target == 0 || GET_MODE (target) != SImode) if (target == 0 || GET_MODE (target) != SImode)
target = gen_reg_rtx (SImode); target = gen_reg_rtx (SImode);
cmp_result = mips_expand_builtin_compare_1 (icode, cond, exp,
/* The instruction should have a target operand, an operand for each call_expr_nargs (exp));
argument, and an operand for COND. */
gcc_assert (call_expr_nargs (exp) + 2 == insn_data[icode].n_operands);
/* Prepare the operands to the comparison. */
cmp_result = mips_prepare_builtin_target (icode, 0, 0);
for (argno = 0; argno < call_expr_nargs (exp); argno++)
args[argno] = mips_prepare_builtin_arg (icode, argno + 1, exp, argno);
switch (insn_data[icode].n_operands)
{
case 4:
emit_insn (GEN_FCN (icode) (cmp_result, args[0], args[1],
GEN_INT (cond)));
break;
case 6:
emit_insn (GEN_FCN (icode) (cmp_result, args[0], args[1],
args[2], args[3], GEN_INT (cond)));
break;
default:
gcc_unreachable ();
}
/* If the comparison sets more than one register, we define the result /* If the comparison sets more than one register, we define the result
to be 0 if all registers are false and -1 if all registers are true. to be 0 if all registers are false and -1 if all registers are true.
......
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