expr.c (cmpstr_optab, [...]): New.

* expr.c (cmpstr_optab, cmpmem_optab): New.
	* genopinit.c: Initialize them.
	* optabs.h: Declare them.
	* optabs.c (init_optabs): Clear them.
	(prepare_cmp_insn):  Use cmpstr_optab and cmpmem_optab to find
	block memory compare insns, not conditional chains.  Restructure
	the fallback generation of a call to memcmp/bcmp for better
	readability.

From-SVN: r72185
This commit is contained in:
Zack Weinberg 2003-10-07 07:25:32 +00:00 committed by Zack Weinberg
parent d04a575f62
commit 118355a03a
5 changed files with 77 additions and 86 deletions

View File

@ -1,3 +1,14 @@
2003-10-07 Zack Weinberg <zack@codesourcery.com>
* expr.c (cmpstr_optab, cmpmem_optab): New.
* genopinit.c: Initialize them.
* optabs.h: Declare them.
* optabs.c (init_optabs): Clear them.
(prepare_cmp_insn): Use cmpstr_optab and cmpmem_optab to find
block memory compare insns, not conditional chains. Restructure
the fallback generation of a call to memcmp/bcmp for better
readability.
2003-10-07 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.c (MIPS_MAX_FIRST_STACK_STEP): New macro.

View File

@ -235,6 +235,11 @@ enum insn_code movstr_optab[NUM_MACHINE_MODES];
/* This array records the insn_code of insns to perform block clears. */
enum insn_code clrstr_optab[NUM_MACHINE_MODES];
/* These arrays record the insn_code of two different kinds of insns
to perform block compares. */
enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
/* Stack of EXPR_WITH_FILE_LOCATION nested expressions. */
struct file_stack *expr_wfl_stack;

View File

@ -150,7 +150,9 @@ static const char * const optabs[] =
"reload_in_optab[$A] = CODE_FOR_$(reload_in$a$)",
"reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)",
"movstr_optab[$A] = CODE_FOR_$(movstr$a$)",
"clrstr_optab[$A] = CODE_FOR_$(clrstr$a$)" };
"clrstr_optab[$A] = CODE_FOR_$(clrstr$a$)",
"cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)",
"cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)" };
static void gen_insn (rtx);

View File

@ -3571,105 +3571,71 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
if (mode == BLKmode)
{
enum machine_mode cmp_mode, result_mode;
enum insn_code cmp_code;
tree length_type;
rtx libfunc;
rtx result;
enum machine_mode result_mode;
rtx opalign ATTRIBUTE_UNUSED
rtx opalign
= GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
if (size == 0)
abort ();
emit_queue ();
x = protect_from_queue (x, 0);
y = protect_from_queue (y, 0);
size = protect_from_queue (size, 0);
if (size == 0)
abort ();
#ifdef HAVE_cmpmemqi
if (HAVE_cmpmemqi
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
/* Try to use a memory block compare insn - either cmpstr
or cmpmem will do. */
for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
cmp_mode != VOIDmode;
cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
{
result_mode = insn_data[(int) CODE_FOR_cmpmemqi].operand[0].mode;
cmp_code = cmpmem_optab[cmp_mode];
if (cmp_code == CODE_FOR_nothing)
cmp_code = cmpstr_optab[cmp_mode];
if (cmp_code == CODE_FOR_nothing)
continue;
/* Must make sure the size fits the insn's mode. */
if ((GET_CODE (size) == CONST_INT
&& INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
|| (GET_MODE_BITSIZE (GET_MODE (size))
> GET_MODE_BITSIZE (cmp_mode)))
continue;
result_mode = insn_data[cmp_code].operand[0].mode;
result = gen_reg_rtx (result_mode);
emit_insn (gen_cmpmemqi (result, x, y, size, opalign));
size = convert_to_mode (cmp_mode, size, 1);
emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
*px = result;
*py = const0_rtx;
*pmode = result_mode;
return;
}
else
#endif
#ifdef HAVE_cmpmemhi
if (HAVE_cmpmemhi
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
{
result_mode = insn_data[(int) CODE_FOR_cmpmemhi].operand[0].mode;
result = gen_reg_rtx (result_mode);
emit_insn (gen_cmpmemhi (result, x, y, size, opalign));
}
else
#endif
#ifdef HAVE_cmpmemsi
if (HAVE_cmpmemsi)
{
result_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
result = gen_reg_rtx (result_mode);
size = protect_from_queue (size, 0);
emit_insn (gen_cmpmemsi (result, x, y,
convert_to_mode (SImode, size, 1),
opalign));
}
else
#endif
#ifdef HAVE_cmpstrqi
if (HAVE_cmpstrqi
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
{
result_mode = insn_data[(int) CODE_FOR_cmpstrqi].operand[0].mode;
result = gen_reg_rtx (result_mode);
emit_insn (gen_cmpstrqi (result, x, y, size, opalign));
}
else
#endif
#ifdef HAVE_cmpstrhi
if (HAVE_cmpstrhi
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
{
result_mode = insn_data[(int) CODE_FOR_cmpstrhi].operand[0].mode;
result = gen_reg_rtx (result_mode);
emit_insn (gen_cmpstrhi (result, x, y, size, opalign));
}
else
#endif
#ifdef HAVE_cmpstrsi
if (HAVE_cmpstrsi)
{
result_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
result = gen_reg_rtx (result_mode);
size = protect_from_queue (size, 0);
emit_insn (gen_cmpstrsi (result, x, y,
convert_to_mode (SImode, size, 1),
opalign));
}
else
#endif
{
/* Otherwise call a library function, memcmp if we've got it,
bcmp otherwise. */
#ifdef TARGET_MEM_FUNCTIONS
result = emit_library_call_value (memcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype), size,
TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
libfunc = memcmp_libfunc;
length_type = sizetype;
#else
result = emit_library_call_value (bcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
convert_to_mode (TYPE_MODE (integer_type_node),
size,
TREE_UNSIGNED (integer_type_node)),
TYPE_MODE (integer_type_node));
libfunc = bcmp_libfunc;
length_type = integer_type_node;
#endif
result_mode = TYPE_MODE (integer_type_node);
cmp_mode = TYPE_MODE (length_type);
size = convert_to_mode (TYPE_MODE (length_type), size,
TREE_UNSIGNED (length_type));
result_mode = TYPE_MODE (integer_type_node);
}
result = emit_library_call_value (libfunc, 0, LCT_PURE_MAKE_BLOCK,
result_mode, 3,
XEXP (x, 0), Pmode,
XEXP (y, 0), Pmode,
size, cmp_mode);
*px = result;
*py = const0_rtx;
*pmode = result_mode;
@ -5330,6 +5296,8 @@ init_optabs (void)
{
movstr_optab[i] = CODE_FOR_nothing;
clrstr_optab[i] = CODE_FOR_nothing;
cmpstr_optab[i] = CODE_FOR_nothing;
cmpmem_optab[i] = CODE_FOR_nothing;
#ifdef HAVE_SECONDARY_RELOADS
reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;

View File

@ -348,6 +348,11 @@ extern enum insn_code movstr_optab[NUM_MACHINE_MODES];
/* This array records the insn_code of insns to perform block clears. */
extern enum insn_code clrstr_optab[NUM_MACHINE_MODES];
/* These arrays record the insn_code of two different kinds of insns
to perform block compares. */
extern enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
/* Define functions given in optabs.c. */
/* Expand a binary operation given optab and rtx operands. */