Commit 483c57af by Kito Cheng Committed by Chung-Ju Wu

[NDS32] Implement strlensi pattern.

gcc/
	* config/nds32/nds32-memory-manipulation.c (nds32_expand_strlen): New
	function.
	* config/nds32/nds32-multiple.md (strlensi): New pattern.
	* config/nds32/nds32-protos.h (nds32_expand_strlen): Declare function.

Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>

From-SVN: r258425
parent 3999578c
2018-03-11 Kito Cheng <kito.cheng@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32-memory-manipulation.c (nds32_expand_strlen): New
function.
* config/nds32/nds32-multiple.md (strlensi): New pattern.
* config/nds32/nds32-protos.h (nds32_expand_strlen): Declare function.
2018-03-11 Monk Chiang <sh.chiang04@gmail.com>
Kito Cheng <kito.cheng@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com>
......
......@@ -848,6 +848,69 @@ nds32_expand_setmem (rtx dstmem, rtx size, rtx value, rtx align,
/* ------------------------------------------------------------------------ */
/* Auxiliary function for expand strlen pattern. */
bool
nds32_expand_strlen (rtx result, rtx str,
rtx target_char, rtx align ATTRIBUTE_UNUSED)
{
rtx base_reg, backup_base_reg;
rtx ffb_result;
rtx target_char_ptr, length;
rtx loop_label, tmp;
if (optimize_size || optimize < 3)
return false;
gcc_assert (MEM_P (str));
gcc_assert (CONST_INT_P (target_char) || REG_P (target_char));
base_reg = copy_to_mode_reg (SImode, XEXP (str, 0));
loop_label = gen_label_rtx ();
ffb_result = gen_reg_rtx (Pmode);
tmp = gen_reg_rtx (SImode);
backup_base_reg = gen_reg_rtx (SImode);
/* Emit loop version of strlen.
move $backup_base, $base
.Lloop:
lmw.bim $tmp, [$base], $tmp, 0
ffb $ffb_result, $tmp, $target_char ! is there $target_char?
beqz $ffb_result, .Lloop
add $last_char_ptr, $base, $ffb_result
sub $length, $last_char_ptr, $backup_base */
/* move $backup_base, $base */
emit_move_insn (backup_base_reg, base_reg);
/* .Lloop: */
emit_label (loop_label);
/* lmw.bim $tmp, [$base], $tmp, 0 */
emit_insn (gen_unaligned_load_update_base_w (base_reg, tmp, base_reg));
/* ffb $ffb_result, $tmp, $target_char ! is there $target_char? */
emit_insn (gen_unspec_ffb (ffb_result, tmp, target_char));
/* beqz $ffb_result, .Lloop */
emit_cmp_and_jump_insns (ffb_result, const0_rtx, EQ, NULL,
SImode, 1, loop_label);
/* add $target_char_ptr, $base, $ffb_result */
target_char_ptr = expand_binop (Pmode, add_optab, base_reg,
ffb_result, NULL_RTX, 0, OPTAB_WIDEN);
/* sub $length, $target_char_ptr, $backup_base */
length = expand_binop (Pmode, sub_optab, target_char_ptr,
backup_base_reg, NULL_RTX, 0, OPTAB_WIDEN);
emit_move_insn (result, length);
return true;
}
/* ------------------------------------------------------------------------ */
/* Functions to expand load_multiple and store_multiple.
They are auxiliary extern functions to help create rtx template.
Check nds32-multiple.md file for the patterns. */
......
......@@ -3750,6 +3750,19 @@
;; ------------------------------------------------------------------------
(define_expand "strlensi"
[(match_operand:SI 0 "register_operand")
(match_operand:BLK 1 "memory_operand")
(match_operand:QI 2 "nds32_reg_constant_operand")
(match_operand 3 "const_int_operand")]
"TARGET_EXT_STRING"
{
if (nds32_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
DONE;
FAIL;
})
(define_expand "setmemsi"
[(use (match_operand:BLK 0 "memory_operand"))
(use (match_operand:SI 1 "nds32_reg_constant_operand"))
......
......@@ -70,6 +70,7 @@ extern rtx nds32_expand_load_multiple (int, int, rtx, rtx, bool, rtx *);
extern rtx nds32_expand_store_multiple (int, int, rtx, rtx, bool, rtx *);
extern bool nds32_expand_movmemsi (rtx, rtx, rtx, rtx);
extern bool nds32_expand_setmem (rtx, rtx, rtx, rtx, rtx, rtx);
extern bool nds32_expand_strlen (rtx, rtx, rtx, rtx);
/* Auxiliary functions for expand unalign load instruction. */
......
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