Commit 358b8f01 by Jakub Jelinek Committed by Jakub Jelinek

optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists, then fall back to cmpstrM.

	* optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists,
	then fall back to cmpstrM.
	* builtins.c (expand_builtin_memcmp): Likewise.
	* config/s390/s390-protos.h (s390_expand_cmpstr): Rename to...
	(s390_expand_cmpmem): ... this.
	* config/s390/s390.md (cmpmemdi, cmpmemsi, cmpmem_short_64,
	cmpmem_short_31, cmpmem_long_64, cmpmem_long_31): Renamed
	from cmpstr* patterns.  Rename call to s390_expand_cmpstr
	to s390_expand_cmpmem.
	* config/s390/s390.c (s390_expand_cmpstr): Rename to...
	(s390_expand_cmpstr): ... this.  Rename cmpstr* instructions
	to cmpmem*.
	* config/i370/i370.md (cmpmemsi, cmpmemsi_1): Renamed from
	cmpstr* patterns.
	* doc/md.texi (cmpstrM): Describe as String compare insn, not
	Block compare insn.
	(cmpmemM): Add.

	* gcc.dg/20030711-1.c: New test.

From-SVN: r69243
parent 8634e925
2003-07-11 Jakub Jelinek <jakub@redhat.com>
* optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists,
then fall back to cmpstrM.
* builtins.c (expand_builtin_memcmp): Likewise.
* config/s390/s390-protos.h (s390_expand_cmpstr): Rename to...
(s390_expand_cmpmem): ... this.
* config/s390/s390.md (cmpmemdi, cmpmemsi, cmpmem_short_64,
cmpmem_short_31, cmpmem_long_64, cmpmem_long_31): Renamed
from cmpstr* patterns. Rename call to s390_expand_cmpstr
to s390_expand_cmpmem.
* config/s390/s390.c (s390_expand_cmpstr): Rename to...
(s390_expand_cmpstr): ... this. Rename cmpstr* instructions
to cmpmem*.
* config/i370/i370.md (cmpmemsi, cmpmemsi_1): Renamed from
cmpstr* patterns.
* doc/md.texi (cmpstrM): Describe as String compare insn, not
Block compare insn.
(cmpmemM): Add.
2003-07-11 Loren James Rittle <ljrittle@acm.org> 2003-07-11 Loren James Rittle <ljrittle@acm.org>
* config/i386/freebsd.h (SET_ASM_OP): Remove. * config/i386/freebsd.h (SET_ASM_OP): Remove.
......
...@@ -3196,7 +3196,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, ...@@ -3196,7 +3196,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
return expand_expr (result, target, mode, EXPAND_NORMAL); return expand_expr (result, target, mode, EXPAND_NORMAL);
} }
#ifdef HAVE_cmpstrsi #if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi
{ {
rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result; rtx result;
...@@ -3206,8 +3206,19 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, ...@@ -3206,8 +3206,19 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
int arg2_align int arg2_align
= get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
enum machine_mode insn_mode enum machine_mode insn_mode;
= insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
#ifdef HAVE_cmpmemsi
if (HAVE_cmpmemsi)
insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
else
#endif
#ifdef HAVE_cmpstrsi
if (HAVE_cmpstrsi)
insn_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
else
#endif
return 0;
/* If we don't have POINTER_TYPE, call the function. */ /* If we don't have POINTER_TYPE, call the function. */
if (arg1_align == 0 || arg2_align == 0) if (arg1_align == 0 || arg2_align == 0)
...@@ -3223,11 +3234,19 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, ...@@ -3223,11 +3234,19 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
arg1_rtx = get_memory_rtx (arg1); arg1_rtx = get_memory_rtx (arg1);
arg2_rtx = get_memory_rtx (arg2); arg2_rtx = get_memory_rtx (arg2);
arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
if (!HAVE_cmpstrsi) #ifdef HAVE_cmpmemsi
insn = NULL_RTX; if (HAVE_cmpmemsi)
insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
GEN_INT (MIN (arg1_align, arg2_align)));
else else
#endif
#ifdef HAVE_cmpstrsi
if (HAVE_cmpstrsi)
insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx, insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
GEN_INT (MIN (arg1_align, arg2_align))); GEN_INT (MIN (arg1_align, arg2_align)));
else
#endif
abort ();
if (insn) if (insn)
emit_insn (insn); emit_insn (insn);
......
...@@ -474,10 +474,10 @@ check_label_emit (); ...@@ -474,10 +474,10 @@ check_label_emit ();
) )
; ;
; cmpstrsi instruction pattern(s). ; cmpmemsi instruction pattern(s).
; ;
(define_expand "cmpstrsi" (define_expand "cmpmemsi"
[(set (match_operand:SI 0 "general_operand" "") [(set (match_operand:SI 0 "general_operand" "")
(compare (match_operand:BLK 1 "general_operand" "") (compare (match_operand:BLK 1 "general_operand" "")
(match_operand:BLK 2 "general_operand" ""))) (match_operand:BLK 2 "general_operand" "")))
...@@ -545,7 +545,7 @@ check_label_emit (); ...@@ -545,7 +545,7 @@ check_label_emit ();
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len);
/* Compare! */ /* Compare! */
emit_insn (gen_cmpstrsi_1 (result, reg1, reg2)); emit_insn (gen_cmpmemsi_1 (result, reg1, reg2));
} }
DONE; DONE;
}") }")
...@@ -569,7 +569,7 @@ check_label_emit (); ...@@ -569,7 +569,7 @@ check_label_emit ();
; Compare a block that is larger than 255 bytes in length. ; Compare a block that is larger than 255 bytes in length.
(define_insn "cmpstrsi_1" (define_insn "cmpmemsi_1"
[(set (match_operand:SI 0 "register_operand" "+d") [(set (match_operand:SI 0 "register_operand" "+d")
(compare (compare
(mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0)) (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0))
......
...@@ -68,7 +68,7 @@ extern void emit_symbolic_move PARAMS ((rtx *)); ...@@ -68,7 +68,7 @@ extern void emit_symbolic_move PARAMS ((rtx *));
extern void s390_load_address PARAMS ((rtx, rtx)); extern void s390_load_address PARAMS ((rtx, rtx));
extern void s390_expand_movstr PARAMS ((rtx, rtx, rtx)); extern void s390_expand_movstr PARAMS ((rtx, rtx, rtx));
extern void s390_expand_clrstr PARAMS ((rtx, rtx)); extern void s390_expand_clrstr PARAMS ((rtx, rtx));
extern void s390_expand_cmpstr PARAMS ((rtx, rtx, rtx, rtx)); extern void s390_expand_cmpmem PARAMS ((rtx, rtx, rtx, rtx));
extern rtx s390_return_addr_rtx PARAMS ((int, rtx)); extern rtx s390_return_addr_rtx PARAMS ((int, rtx));
extern void s390_output_symbolic_const PARAMS ((FILE *, rtx)); extern void s390_output_symbolic_const PARAMS ((FILE *, rtx));
......
...@@ -3116,16 +3116,16 @@ s390_expand_clrstr (dst, len) ...@@ -3116,16 +3116,16 @@ s390_expand_clrstr (dst, len)
and return the result in TARGET. */ and return the result in TARGET. */
void void
s390_expand_cmpstr (target, op0, op1, len) s390_expand_cmpmem (target, op0, op1, len)
rtx target; rtx target;
rtx op0; rtx op0;
rtx op1; rtx op1;
rtx len; rtx len;
{ {
rtx (*gen_short) PARAMS ((rtx, rtx, rtx)) = rtx (*gen_short) PARAMS ((rtx, rtx, rtx)) =
TARGET_64BIT ? gen_cmpstr_short_64 : gen_cmpstr_short_31; TARGET_64BIT ? gen_cmpmem_short_64 : gen_cmpmem_short_31;
rtx (*gen_long) PARAMS ((rtx, rtx, rtx, rtx)) = rtx (*gen_long) PARAMS ((rtx, rtx, rtx, rtx)) =
TARGET_64BIT ? gen_cmpstr_long_64 : gen_cmpstr_long_31; TARGET_64BIT ? gen_cmpmem_long_64 : gen_cmpmem_long_31;
rtx (*gen_result) PARAMS ((rtx)) = rtx (*gen_result) PARAMS ((rtx)) =
GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si; GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si;
......
...@@ -1958,33 +1958,33 @@ ...@@ -1958,33 +1958,33 @@
(set_attr "length" "8")]) (set_attr "length" "8")])
; ;
; cmpstrM instruction pattern(s). ; cmpmemM instruction pattern(s).
; ;
(define_expand "cmpstrdi" (define_expand "cmpmemdi"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(compare:DI (match_operand:BLK 1 "memory_operand" "") (compare:DI (match_operand:BLK 1 "memory_operand" "")
(match_operand:BLK 2 "memory_operand" "") ) ) (match_operand:BLK 2 "memory_operand" "") ) )
(use (match_operand:DI 3 "general_operand" "")) (use (match_operand:DI 3 "general_operand" ""))
(use (match_operand:DI 4 "" ""))] (use (match_operand:DI 4 "" ""))]
"TARGET_64BIT" "TARGET_64BIT"
"s390_expand_cmpstr (operands[0], operands[1], "s390_expand_cmpmem (operands[0], operands[1],
operands[2], operands[3]); DONE;") operands[2], operands[3]); DONE;")
(define_expand "cmpstrsi" (define_expand "cmpmemsi"
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand:SI 0 "register_operand" "")
(compare:SI (match_operand:BLK 1 "memory_operand" "") (compare:SI (match_operand:BLK 1 "memory_operand" "")
(match_operand:BLK 2 "memory_operand" "") ) ) (match_operand:BLK 2 "memory_operand" "") ) )
(use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 3 "general_operand" ""))
(use (match_operand:SI 4 "" ""))] (use (match_operand:SI 4 "" ""))]
"" ""
"s390_expand_cmpstr (operands[0], operands[1], "s390_expand_cmpmem (operands[0], operands[1],
operands[2], operands[3]); DONE;") operands[2], operands[3]); DONE;")
; Compare a block that is up to 256 bytes in length. ; Compare a block that is up to 256 bytes in length.
; The block length is taken as (operands[2] % 256) + 1. ; The block length is taken as (operands[2] % 256) + 1.
(define_insn "cmpstr_short_64" (define_insn "cmpmem_short_64"
[(set (reg:CCS 33) [(set (reg:CCS 33)
(compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q") (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
(match_operand:BLK 1 "memory_operand" "Q,Q"))) (match_operand:BLK 1 "memory_operand" "Q,Q")))
...@@ -2012,7 +2012,7 @@ ...@@ -2012,7 +2012,7 @@
(set_attr "atype" "*,agen") (set_attr "atype" "*,agen")
(set_attr "length" "*,14")]) (set_attr "length" "*,14")])
(define_insn "cmpstr_short_31" (define_insn "cmpmem_short_31"
[(set (reg:CCS 33) [(set (reg:CCS 33)
(compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q") (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
(match_operand:BLK 1 "memory_operand" "Q,Q"))) (match_operand:BLK 1 "memory_operand" "Q,Q")))
...@@ -2042,7 +2042,7 @@ ...@@ -2042,7 +2042,7 @@
; Compare a block of arbitrary length. ; Compare a block of arbitrary length.
(define_insn "cmpstr_long_64" (define_insn "cmpmem_long_64"
[(clobber (match_operand:TI 0 "register_operand" "=d")) [(clobber (match_operand:TI 0 "register_operand" "=d"))
(clobber (match_operand:TI 1 "register_operand" "=d")) (clobber (match_operand:TI 1 "register_operand" "=d"))
(set (reg:CCS 33) (set (reg:CCS 33)
...@@ -2055,7 +2055,7 @@ ...@@ -2055,7 +2055,7 @@
[(set_attr "op_type" "RR") [(set_attr "op_type" "RR")
(set_attr "type" "vs")]) (set_attr "type" "vs")])
(define_insn "cmpstr_long_31" (define_insn "cmpmem_long_31"
[(clobber (match_operand:DI 0 "register_operand" "=d")) [(clobber (match_operand:DI 0 "register_operand" "=d"))
(clobber (match_operand:DI 1 "register_operand" "=d")) (clobber (match_operand:DI 1 "register_operand" "=d"))
(set (reg:CCS 33) (set (reg:CCS 33)
......
...@@ -2799,7 +2799,7 @@ The use for multiple @code{clrstr@var{m}} is as for @code{movstr@var{m}}. ...@@ -2799,7 +2799,7 @@ The use for multiple @code{clrstr@var{m}} is as for @code{movstr@var{m}}.
@cindex @code{cmpstr@var{m}} instruction pattern @cindex @code{cmpstr@var{m}} instruction pattern
@item @samp{cmpstr@var{m}} @item @samp{cmpstr@var{m}}
Block compare instruction, with five operands. Operand 0 is the output; String compare instruction, with five operands. Operand 0 is the output;
it has mode @var{m}. The remaining four operands are like the operands it has mode @var{m}. The remaining four operands are like the operands
of @samp{movstr@var{m}}. The two memory blocks specified are compared of @samp{movstr@var{m}}. The two memory blocks specified are compared
byte by byte in lexicographic order starting at the beginning of each byte by byte in lexicographic order starting at the beginning of each
...@@ -2809,6 +2809,16 @@ that may access an invalid page or segment and cause a fault. The ...@@ -2809,6 +2809,16 @@ that may access an invalid page or segment and cause a fault. The
effect of the instruction is to store a value in operand 0 whose sign effect of the instruction is to store a value in operand 0 whose sign
indicates the result of the comparison. indicates the result of the comparison.
@cindex @code{cmpmem@var{m}} instruction pattern
@item @samp{cmpmem@var{m}}
Block compare instruction, with five operands like the operands
of @samp{cmpstr@var{m}}. The two memory blocks specified are compared
byte by byte in lexicographic order starting at the beginning of each
block. Unlike @samp{cmpstr@var{m}} the instruction can prefetch
any bytes in the two memory blocks. The effect of the instruction is
to store a value in operand 0 whose sign indicates the result of the
comparison.
@cindex @code{strlen@var{m}} instruction pattern @cindex @code{strlen@var{m}} instruction pattern
@item @samp{strlen@var{m}} @item @samp{strlen@var{m}}
Compute the length of a string, with three operands. Compute the length of a string, with three operands.
......
...@@ -3579,6 +3579,40 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, ...@@ -3579,6 +3579,40 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
if (size == 0) if (size == 0)
abort (); abort ();
#ifdef HAVE_cmpmemqi
if (HAVE_cmpmemqi
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
{
result_mode = insn_data[(int) CODE_FOR_cmpmemqi].operand[0].mode;
result = gen_reg_rtx (result_mode);
emit_insn (gen_cmpmemqi (result, x, y, size, opalign));
}
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 #ifdef HAVE_cmpstrqi
if (HAVE_cmpstrqi if (HAVE_cmpstrqi
&& GET_CODE (size) == CONST_INT && GET_CODE (size) == CONST_INT
......
2003-07-11 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/20030711-1.c: New test.
2003-07-11 Nathan Sidwell <nathan@codesourcery.com> 2003-07-11 Nathan Sidwell <nathan@codesourcery.com>
PR c++/11050 PR c++/11050
......
/* Test whether strncmp has not been "optimized" into memcmp
nor any code with memcmp semantics. */
/* { dg-do run { target i?86-*-linux* x86_64-*-linux* ia64-*-linux* alpha*-*-linux* powerpc*-*-linux* s390*-*-linux* sparc*-*-linux* } } */
/* { dg-options "-O2" } */
#include <sys/mman.h>
#include <stdlib.h>
void __attribute__((noinline)) test (const char *p)
{
if (__builtin_strncmp (p, "abcdefghijklmnopq", 17) == 0)
abort ();
}
int main (void)
{
char *p = mmap (NULL, 131072, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (p == MAP_FAILED)
return 0;
if (munmap (p + 65536, 65536) < 0)
return 0;
__builtin_memcpy (p + 65536 - 5, "abcd", 5);
test (p + 65536 - 5);
return 0;
}
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