Commit 40c1d5f8 by Adrian Straetling Committed by Ulrich Weigand

builtins.c: (expand_builtin_memcmp, expand_builtin_strncmp): s/cmpstrsi/cmpstrnsi

2005-07-12  Adrian Straetling  <straetling@de.ibm.com>

	* builtins.c: (expand_builtin_memcmp, expand_builtin_strncmp):
	s/cmpstrsi/cmpstrnsi
	(expand_builtin_strcmp): Rewrite to support both 'cmpstrsi' and
	'cmpstrnsi'.
	* optabs.c: (prepare_cmp_insn): Add availability of 'cmpstrn'.
	(init_optabs): Initialize cmpstrn_optab.
	* optabs.h: (enum insn_code cmpstrn_optab): Declare.
	* genopinit.c: (optabs[]): Add 'cmpstrn' to initialisation.
	* expr.c: (enum insn_code cmpstrn_optab): Declare.
	* config/i386/i386.md: s/cmpstr/cmpstrn
	* config/c4x/c4x.md: s/cmpstr/cmpstrn
	* doc/md.texi: Update documentation.

From-SVN: r101916
parent 72f93778
2005-07-12 Adrian Straetling <straetling@de.ibm.com>
* builtins.c: (expand_builtin_memcmp, expand_builtin_strncmp):
s/cmpstrsi/cmpstrnsi
(expand_builtin_strcmp): Rewrite to support both 'cmpstrsi' and
'cmpstrnsi'.
* optabs.c: (prepare_cmp_insn): Add availability of 'cmpstrn'.
(init_optabs): Initialize cmpstrn_optab.
* optabs.h: (enum insn_code cmpstrn_optab): Declare.
* genopinit.c: (optabs[]): Add 'cmpstrn' to initialisation.
* expr.c: (enum insn_code cmpstrn_optab): Declare.
* config/i386/i386.md: s/cmpstr/cmpstrn
* config/c4x/c4x.md: s/cmpstr/cmpstrn
* doc/md.texi: Update documentation.
2005-07-11 Richard Henderson <rth@redhat.com> 2005-07-11 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (alpha_gimplify_va_arg_1): Use * config/alpha/alpha.c (alpha_gimplify_va_arg_1): Use
......
...@@ -5714,7 +5714,7 @@ ...@@ -5714,7 +5714,7 @@
}") }")
(define_insn "*cmpstrqi" (define_insn "*cmpstrnqi"
[(set (match_operand:QI 0 "ext_reg_operand" "=d") [(set (match_operand:QI 0 "ext_reg_operand" "=d")
(compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a")) (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a"))
(mem:BLK (match_operand:QI 2 "addr_reg_operand" "+a")))) (mem:BLK (match_operand:QI 2 "addr_reg_operand" "+a"))))
...@@ -5731,7 +5731,7 @@ ...@@ -5731,7 +5731,7 @@
return \"\"; return \"\";
}") }")
(define_expand "cmpstrqi" (define_expand "cmpstrnqi"
[(parallel [(set (match_operand:QI 0 "reg_operand" "") [(parallel [(set (match_operand:QI 0 "reg_operand" "")
(compare:QI (match_operand:BLK 1 "general_operand" "") (compare:QI (match_operand:BLK 1 "general_operand" "")
(match_operand:BLK 2 "general_operand" ""))) (match_operand:BLK 2 "general_operand" "")))
......
...@@ -17446,7 +17446,7 @@ ...@@ -17446,7 +17446,7 @@
(set_attr "memory" "store") (set_attr "memory" "store")
(set_attr "mode" "QI")]) (set_attr "mode" "QI")])
(define_expand "cmpstrsi" (define_expand "cmpstrnsi"
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand:SI 0 "register_operand" "")
(compare:SI (match_operand:BLK 1 "general_operand" "") (compare:SI (match_operand:BLK 1 "general_operand" "")
(match_operand:BLK 2 "general_operand" ""))) (match_operand:BLK 2 "general_operand" "")))
...@@ -17487,8 +17487,8 @@ ...@@ -17487,8 +17487,8 @@
emit_move_insn (operands[0], const0_rtx); emit_move_insn (operands[0], const0_rtx);
DONE; DONE;
} }
emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align, emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align,
operands[1], operands[2])); operands[1], operands[2]));
} }
else else
{ {
...@@ -17496,8 +17496,8 @@ ...@@ -17496,8 +17496,8 @@
emit_insn (gen_cmpdi_1_rex64 (countreg, countreg)); emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
else else
emit_insn (gen_cmpsi_1 (countreg, countreg)); emit_insn (gen_cmpsi_1 (countreg, countreg));
emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align, emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
operands[1], operands[2])); operands[1], operands[2]));
} }
outlow = gen_lowpart (QImode, out); outlow = gen_lowpart (QImode, out);
...@@ -17528,7 +17528,7 @@ ...@@ -17528,7 +17528,7 @@
;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is ;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is
;; zero. Emit extra code to make sure that a zero-length compare is EQ. ;; zero. Emit extra code to make sure that a zero-length compare is EQ.
(define_expand "cmpstrqi_nz_1" (define_expand "cmpstrnqi_nz_1"
[(parallel [(set (reg:CC FLAGS_REG) [(parallel [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand 4 "memory_operand" "") (compare:CC (match_operand 4 "memory_operand" "")
(match_operand 5 "memory_operand" ""))) (match_operand 5 "memory_operand" "")))
...@@ -17541,7 +17541,7 @@ ...@@ -17541,7 +17541,7 @@
"" ""
"") "")
(define_insn "*cmpstrqi_nz_1" (define_insn "*cmpstrnqi_nz_1"
[(set (reg:CC FLAGS_REG) [(set (reg:CC FLAGS_REG)
(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0")) (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
(mem:BLK (match_operand:SI 5 "register_operand" "1")))) (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
...@@ -17557,7 +17557,7 @@ ...@@ -17557,7 +17557,7 @@
(set_attr "mode" "QI") (set_attr "mode" "QI")
(set_attr "prefix_rep" "1")]) (set_attr "prefix_rep" "1")])
(define_insn "*cmpstrqi_nz_rex_1" (define_insn "*cmpstrnqi_nz_rex_1"
[(set (reg:CC FLAGS_REG) [(set (reg:CC FLAGS_REG)
(compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0")) (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
(mem:BLK (match_operand:DI 5 "register_operand" "1")))) (mem:BLK (match_operand:DI 5 "register_operand" "1"))))
...@@ -17575,7 +17575,7 @@ ...@@ -17575,7 +17575,7 @@
;; The same, but the count is not known to not be zero. ;; The same, but the count is not known to not be zero.
(define_expand "cmpstrqi_1" (define_expand "cmpstrnqi_1"
[(parallel [(set (reg:CC FLAGS_REG) [(parallel [(set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_operand 2 "register_operand" "") (if_then_else:CC (ne (match_operand 2 "register_operand" "")
(const_int 0)) (const_int 0))
...@@ -17591,7 +17591,7 @@ ...@@ -17591,7 +17591,7 @@
"" ""
"") "")
(define_insn "*cmpstrqi_1" (define_insn "*cmpstrnqi_1"
[(set (reg:CC FLAGS_REG) [(set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2") (if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
(const_int 0)) (const_int 0))
...@@ -17610,7 +17610,7 @@ ...@@ -17610,7 +17610,7 @@
(set_attr "mode" "QI") (set_attr "mode" "QI")
(set_attr "prefix_rep" "1")]) (set_attr "prefix_rep" "1")])
(define_insn "*cmpstrqi_rex_1" (define_insn "*cmpstrnqi_rex_1"
[(set (reg:CC FLAGS_REG) [(set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2") (if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2")
(const_int 0)) (const_int 0))
...@@ -17693,9 +17693,9 @@ ...@@ -17693,9 +17693,9 @@
(set_attr "mode" "QI") (set_attr "mode" "QI")
(set_attr "prefix_rep" "1")]) (set_attr "prefix_rep" "1")])
;; Peephole optimizations to clean up after cmpstr*. This should be ;; Peephole optimizations to clean up after cmpstrn*. This should be
;; handled in combine, but it is not currently up to the task. ;; handled in combine, but it is not currently up to the task.
;; When used for their truth value, the cmpstr* expanders generate ;; When used for their truth value, the cmpstrn* expanders generate
;; code like this: ;; code like this:
;; ;;
;; repz cmpsb ;; repz cmpsb
...@@ -17706,7 +17706,7 @@ ...@@ -17706,7 +17706,7 @@
;; ;;
;; The intermediate three instructions are unnecessary. ;; The intermediate three instructions are unnecessary.
;; This one handles cmpstr*_nz_1... ;; This one handles cmpstrn*_nz_1...
(define_peephole2 (define_peephole2
[(parallel[ [(parallel[
(set (reg:CC FLAGS_REG) (set (reg:CC FLAGS_REG)
...@@ -17738,7 +17738,7 @@ ...@@ -17738,7 +17738,7 @@
(clobber (match_dup 2))])] (clobber (match_dup 2))])]
"") "")
;; ...and this one handles cmpstr*_1. ;; ...and this one handles cmpstrn*_1.
(define_peephole2 (define_peephole2
[(parallel[ [(parallel[
(set (reg:CC FLAGS_REG) (set (reg:CC FLAGS_REG)
......
...@@ -3269,8 +3269,8 @@ operand. ...@@ -3269,8 +3269,8 @@ operand.
The use for multiple @code{setmem@var{m}} is as for @code{movmem@var{m}}. The use for multiple @code{setmem@var{m}} is as for @code{movmem@var{m}}.
@cindex @code{cmpstr@var{m}} instruction pattern @cindex @code{cmpstrn@var{m}} instruction pattern
@item @samp{cmpstr@var{m}} @item @samp{cmpstrn@var{m}}
String 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{movmem@var{m}}. The two memory blocks specified are compared of @samp{movmem@var{m}}. The two memory blocks specified are compared
...@@ -3281,6 +3281,25 @@ that may access an invalid page or segment and cause a fault. The ...@@ -3281,6 +3281,25 @@ 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{cmpstr@var{m}} instruction pattern
@item @samp{cmpstr@var{m}}
String compare instruction, without known maximum length. Operand 0 is the
output; it has mode @var{m}. The second and third operand are the blocks of
memory to be compared; both are @code{mem:BLK} with an address in mode
@code{Pmode}.
The fourth operand is the known shared alignment of the source and
destination, in the form of a @code{const_int} rtx. Thus, if the
compiler knows that both source and destination are word-aligned,
it may provide the value 4 for this operand.
The two memory blocks specified are compared byte by byte in lexicographic
order starting at the beginning of each string. The instruction is not allowed
to prefetch more than one byte at a time since either string may end in the
first byte and reading past 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 indicates the result of the comparison.
@cindex @code{cmpmem@var{m}} instruction pattern @cindex @code{cmpmem@var{m}} instruction pattern
@item @samp{cmpmem@var{m}} @item @samp{cmpmem@var{m}}
Block compare instruction, with five operands like the operands Block compare instruction, with five operands like the operands
......
...@@ -202,9 +202,10 @@ enum insn_code movmem_optab[NUM_MACHINE_MODES]; ...@@ -202,9 +202,10 @@ enum insn_code movmem_optab[NUM_MACHINE_MODES];
/* This array records the insn_code of insns to perform block sets. */ /* This array records the insn_code of insns to perform block sets. */
enum insn_code setmem_optab[NUM_MACHINE_MODES]; enum insn_code setmem_optab[NUM_MACHINE_MODES];
/* These arrays record the insn_code of two different kinds of insns /* These arrays record the insn_code of three different kinds of insns
to perform block compares. */ to perform block compares. */
enum insn_code cmpstr_optab[NUM_MACHINE_MODES]; enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
enum insn_code cmpstrn_optab[NUM_MACHINE_MODES];
enum insn_code cmpmem_optab[NUM_MACHINE_MODES]; enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
/* Synchronization primitives. */ /* Synchronization primitives. */
......
...@@ -169,6 +169,7 @@ static const char * const optabs[] = ...@@ -169,6 +169,7 @@ static const char * const optabs[] =
"reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)", "reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)",
"movmem_optab[$A] = CODE_FOR_$(movmem$a$)", "movmem_optab[$A] = CODE_FOR_$(movmem$a$)",
"cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)", "cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)",
"cmpstrn_optab[$A] = CODE_FOR_$(cmpstrn$a$)",
"cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)", "cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)",
"setmem_optab[$A] = CODE_FOR_$(setmem$a$)", "setmem_optab[$A] = CODE_FOR_$(setmem$a$)",
"sync_add_optab[$A] = CODE_FOR_$(sync_add$I$a$)", "sync_add_optab[$A] = CODE_FOR_$(sync_add$I$a$)",
......
...@@ -3426,6 +3426,8 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, ...@@ -3426,6 +3426,8 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
if (cmp_code == CODE_FOR_nothing) if (cmp_code == CODE_FOR_nothing)
cmp_code = cmpstr_optab[cmp_mode]; cmp_code = cmpstr_optab[cmp_mode];
if (cmp_code == CODE_FOR_nothing) if (cmp_code == CODE_FOR_nothing)
cmp_code = cmpstrn_optab[cmp_mode];
if (cmp_code == CODE_FOR_nothing)
continue; continue;
/* Must make sure the size fits the insn's mode. */ /* Must make sure the size fits the insn's mode. */
...@@ -5090,6 +5092,7 @@ init_optabs (void) ...@@ -5090,6 +5092,7 @@ init_optabs (void)
{ {
movmem_optab[i] = CODE_FOR_nothing; movmem_optab[i] = CODE_FOR_nothing;
cmpstr_optab[i] = CODE_FOR_nothing; cmpstr_optab[i] = CODE_FOR_nothing;
cmpstrn_optab[i] = CODE_FOR_nothing;
cmpmem_optab[i] = CODE_FOR_nothing; cmpmem_optab[i] = CODE_FOR_nothing;
setmem_optab[i] = CODE_FOR_nothing; setmem_optab[i] = CODE_FOR_nothing;
......
...@@ -450,6 +450,7 @@ extern enum insn_code setmem_optab[NUM_MACHINE_MODES]; ...@@ -450,6 +450,7 @@ extern enum insn_code setmem_optab[NUM_MACHINE_MODES];
/* These arrays record the insn_code of two different kinds of insns /* These arrays record the insn_code of two different kinds of insns
to perform block compares. */ to perform block compares. */
extern enum insn_code cmpstr_optab[NUM_MACHINE_MODES]; extern enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
extern enum insn_code cmpstrn_optab[NUM_MACHINE_MODES];
extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES]; extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
/* Synchronization primitives. This first set is atomic operation for /* Synchronization primitives. This first set is atomic operation for
......
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