[NDS32] Implement strlensi pattern.
authorKito Cheng <kito.cheng@gmail.com>
Sun, 11 Mar 2018 08:24:33 +0000 (08:24 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Sun, 11 Mar 2018 08:24:33 +0000 (08:24 +0000)
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

gcc/ChangeLog
gcc/config/nds32/nds32-memory-manipulation.c
gcc/config/nds32/nds32-multiple.md
gcc/config/nds32/nds32-protos.h

index 0cdc24fdbc5ddfba0a6b8f59a8c434f9014a519b..d429cd2883f836fe8d0abadd956748fb5ff989ea 100644 (file)
@@ -1,3 +1,11 @@
+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>
index 13ac8c1cfc8c86fb2bcc9e0a2a1657c5671f8318..8dea13047b6b11ef8d92bd2b359d9129e82a137a 100644 (file)
@@ -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.  */
index 66880c2fd9d999896c4d0e3bb7b4d2d70b24616e..a8f77175927ee4944e20ccc5a284c1c7ce1b80d7 100644 (file)
 
 ;; ------------------------------------------------------------------------
 
+(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"))
index 075206ed208d773aae4604c297e7bf960cbe1e86..e1522f9e5f4cf624695856ed8ef3d98b7513eaa1 100644 (file)
@@ -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.  */