From 483c57af553b22721f46bfdbd2795ac004767a51 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Sun, 11 Mar 2018 08:24:33 +0000 Subject: [PATCH] [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 From-SVN: r258425 --- gcc/ChangeLog | 8 +++ gcc/config/nds32/nds32-memory-manipulation.c | 63 ++++++++++++++++++++ gcc/config/nds32/nds32-multiple.md | 13 ++++ gcc/config/nds32/nds32-protos.h | 1 + 4 files changed, 85 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0cdc24fdbc5..d429cd2883f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2018-03-11 Kito Cheng + Chung-Ju Wu + + * 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 Kito Cheng Chung-Ju Wu diff --git a/gcc/config/nds32/nds32-memory-manipulation.c b/gcc/config/nds32/nds32-memory-manipulation.c index 13ac8c1cfc8..8dea13047b6 100644 --- a/gcc/config/nds32/nds32-memory-manipulation.c +++ b/gcc/config/nds32/nds32-memory-manipulation.c @@ -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. */ diff --git a/gcc/config/nds32/nds32-multiple.md b/gcc/config/nds32/nds32-multiple.md index 66880c2fd9d..a8f77175927 100644 --- a/gcc/config/nds32/nds32-multiple.md +++ b/gcc/config/nds32/nds32-multiple.md @@ -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")) diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h index 075206ed208..e1522f9e5f4 100644 --- a/gcc/config/nds32/nds32-protos.h +++ b/gcc/config/nds32/nds32-protos.h @@ -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. */ -- 2.30.2