diff options
author | Christian Bruel <christian.bruel@st.com> | 2013-11-06 09:49:15 +0100 |
---|---|---|
committer | Christian Bruel <chrbr@gcc.gnu.org> | 2013-11-06 09:49:15 +0100 |
commit | 3a1a7897b7376b8634dfc4862540b02c691b626d (patch) | |
tree | 23b7846a855026c24877941eabd64fa7b50c6aa9 /gcc/config/sh/sh-mem.cc | |
parent | fda1ba0aeacbbe986bd29677a8165e23a0d7d178 (diff) | |
download | gcc-3a1a7897b7376b8634dfc4862540b02c691b626d.zip gcc-3a1a7897b7376b8634dfc4862540b02c691b626d.tar.gz gcc-3a1a7897b7376b8634dfc4862540b02c691b626d.tar.bz2 |
sh-mem.cc (sh_expand_cmpnstr, [...]): Factorize probabilities...
2013-11-06 Christian Bruel <christian.bruel@st.com>
* gcc/config/sh/sh-mem.cc (sh_expand_cmpnstr, sh_expand_cmpstr):
Factorize probabilities, Use adjust_address instead of
adjust_automodify_address when possible. Enable for optimize.
(sh_expand_strlen): New function.
* gcc/config/sh/sh-protos.h (sh_expand_strlen): Declare.
* gcc/config/sh/sh.md (strlensi): New pattern.
(UNSPEC_BUILTIN_STRLEN): Define.
From-SVN: r204445
Diffstat (limited to 'gcc/config/sh/sh-mem.cc')
-rw-r--r-- | gcc/config/sh/sh-mem.cc | 193 |
1 files changed, 134 insertions, 59 deletions
diff --git a/gcc/config/sh/sh-mem.cc b/gcc/config/sh/sh-mem.cc index eabf687..729e848 100644 --- a/gcc/config/sh/sh-mem.cc +++ b/gcc/config/sh/sh-mem.cc @@ -179,32 +179,31 @@ expand_block_move (rtx *operands) return false; } +static int prob_unlikely = REG_BR_PROB_BASE / 10; +static int prob_likely = REG_BR_PROB_BASE / 4; + /* Emit code to perform a strcmp. OPERANDS[0] is the destination. OPERANDS[1] is the first string. OPERANDS[2] is the second string. - OPERANDS[3] is the align. */ + OPERANDS[3] is the known alignment. */ bool sh_expand_cmpstr (rtx *operands) { - rtx s1 = copy_rtx (operands[1]); - rtx s2 = copy_rtx (operands[2]); - rtx s1_addr = copy_addr_to_reg (XEXP (s1, 0)); - rtx s2_addr = copy_addr_to_reg (XEXP (s2, 0)); + rtx addr1 = operands[1]; + rtx addr2 = operands[2]; + rtx s1_addr = copy_addr_to_reg (XEXP (addr1, 0)); + rtx s2_addr = copy_addr_to_reg (XEXP (addr2, 0)); rtx tmp0 = gen_reg_rtx (SImode); rtx tmp1 = gen_reg_rtx (SImode); rtx tmp2 = gen_reg_rtx (SImode); rtx tmp3 = gen_reg_rtx (SImode); + rtx jump; rtx L_return = gen_label_rtx (); rtx L_loop_byte = gen_label_rtx (); rtx L_end_loop_byte = gen_label_rtx (); - - rtx jump, addr1, addr2; - int prob_unlikely = REG_BR_PROB_BASE / 10; - int prob_likely = REG_BR_PROB_BASE / 4; - rtx L_loop_long = gen_label_rtx (); rtx L_end_loop_long = gen_label_rtx (); @@ -220,8 +219,8 @@ sh_expand_cmpstr (rtx *operands) add_int_reg_note (jump, REG_BR_PROB, prob_likely); } - addr1 = adjust_automodify_address (s1, SImode, s1_addr, 0); - addr2 = adjust_automodify_address (s2, SImode, s2_addr, 0); + addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0); + addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0); /* tmp2 is aligned, OK to load. */ emit_move_insn (tmp3, addr2); @@ -276,8 +275,8 @@ sh_expand_cmpstr (rtx *operands) emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, -4)); /* start byte loop. */ - addr1 = adjust_automodify_address (s1, QImode, s1_addr, 0); - addr2 = adjust_automodify_address (s2, QImode, s2_addr, 0); + addr1 = adjust_address (addr1, QImode, 0); + addr2 = adjust_address (addr2, QImode, 0); emit_label (L_loop_byte); @@ -317,27 +316,23 @@ sh_expand_cmpstr (rtx *operands) OPERANDS[1] is the first string. OPERANDS[2] is the second string. OPERANDS[3] is the length. - OPERANDS[4] is the align. */ + OPERANDS[4] is the known alignment. */ bool sh_expand_cmpnstr (rtx *operands) { - rtx s1 = copy_rtx (operands[1]); - rtx s2 = copy_rtx (operands[2]); - - rtx s1_addr = copy_addr_to_reg (XEXP (s1, 0)); - rtx s2_addr = copy_addr_to_reg (XEXP (s2, 0)); + rtx addr1 = operands[1]; + rtx addr2 = operands[2]; + rtx s1_addr = copy_addr_to_reg (XEXP (addr1, 0)); + rtx s2_addr = copy_addr_to_reg (XEXP (addr2, 0)); rtx tmp0 = gen_reg_rtx (SImode); rtx tmp1 = gen_reg_rtx (SImode); rtx tmp2 = gen_reg_rtx (SImode); + rtx jump; rtx L_return = gen_label_rtx (); rtx L_loop_byte = gen_label_rtx (); rtx L_end_loop_byte = gen_label_rtx (); - rtx jump, addr1, addr2; - int prob_unlikely = REG_BR_PROB_BASE / 10; - int prob_likely = REG_BR_PROB_BASE / 4; - rtx len = force_reg (SImode, operands[3]); int constp = (CONST_INT_P (operands[3])); int bytes = (constp ? INTVAL (operands[3]) : 0); @@ -366,10 +361,10 @@ sh_expand_cmpnstr (rtx *operands) add_int_reg_note (jump, REG_BR_PROB, prob_likely); } - addr1 = adjust_automodify_address (s1, SImode, s1_addr, 0); - addr2 = adjust_automodify_address (s2, SImode, s2_addr, 0); + addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0); + addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0); - /* words count. */ + /* word count. Do we have iterations ? */ emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2))); /*start long loop. */ @@ -429,48 +424,128 @@ sh_expand_cmpnstr (rtx *operands) emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, -4)); } - addr1 = adjust_automodify_address (s1, QImode, s1_addr, 0); - addr2 = adjust_automodify_address (s2, QImode, s2_addr, 0); + addr1 = adjust_address (addr1, QImode, 0); + addr2 = adjust_address (addr2, QImode, 0); + + emit_label (L_loop_byte); + + emit_insn (gen_extendqisi2 (tmp2, addr2)); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 1)); + + emit_insn (gen_extendqisi2 (tmp1, addr1)); + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 1)); + + emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx)); + jump = emit_jump_insn (gen_branch_true (L_end_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + emit_insn (gen_cmpeqsi_t (tmp1, tmp2)); + if (flag_delayed_branch) + emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); + jump = emit_jump_insn (gen_branch_false (L_end_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + if (TARGET_SH2) + emit_insn (gen_dect (len, len)); + else + { + emit_insn (gen_addsi3 (len, len, GEN_INT (-1))); + emit_insn (gen_tstsi_t (len, len)); + } + + jump = emit_jump_insn (gen_branch_false (L_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + /* end byte loop. */ + + emit_label (L_end_loop_byte); + + if (! flag_delayed_branch) + emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); + emit_insn (gen_zero_extendqisi2 (tmp1, gen_lowpart (QImode, tmp1))); + + emit_label (L_return); + + emit_insn (gen_subsi3 (operands[0], tmp1, tmp2)); + + return true; +} + +/* Emit code to perform a strlen + + OPERANDS[0] is the destination. + OPERANDS[1] is the string. + OPERANDS[2] is the char to search. + OPERANDS[3] is the alignment. */ +bool +sh_expand_strlen (rtx *operands) +{ + rtx addr1 = operands[1]; + rtx current_addr = copy_addr_to_reg (XEXP (addr1, 0)); + rtx start_addr = gen_reg_rtx (Pmode); + rtx tmp0 = gen_reg_rtx (SImode); + rtx tmp1 = gen_reg_rtx (SImode); + rtx L_return = gen_label_rtx (); + rtx L_loop_byte = gen_label_rtx (); + + rtx jump; + rtx L_loop_long = gen_label_rtx (); + rtx L_end_loop_long = gen_label_rtx (); + + int align = INTVAL (operands[3]); + + emit_move_insn (operands[0], GEN_INT (-1)); + + /* remember start of string. */ + emit_move_insn (start_addr, current_addr); + + if (align < 4) + { + emit_insn (gen_tstsi_t (GEN_INT (3), current_addr)); + jump = emit_jump_insn (gen_branch_false (L_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + } + + emit_move_insn (tmp0, operands[2]); + + addr1 = adjust_automodify_address (addr1, SImode, current_addr, 0); + + /*start long loop. */ + emit_label (L_loop_long); + + /* tmp1 is aligned, OK to load. */ + emit_move_insn (tmp1, addr1); + emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 4)); + + /* Is there a 0 byte ? */ + emit_insn (gen_cmpstr_t (tmp0, tmp1)); - emit_label (L_loop_byte); + jump = emit_jump_insn (gen_branch_false (L_loop_long)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + /* end loop. */ - emit_insn (gen_extendqisi2 (tmp2, addr2)); - emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 1)); + emit_label (L_end_loop_long); - emit_insn (gen_extendqisi2 (tmp1, addr1)); - emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 1)); + emit_move_insn (current_addr, plus_constant (Pmode, current_addr, -4)); - emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx)); - jump = emit_jump_insn (gen_branch_true (L_end_loop_byte)); - add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + /* start byte loop. */ + addr1 = adjust_address (addr1, QImode, 0); - emit_insn (gen_cmpeqsi_t (tmp1, tmp2)); - if (flag_delayed_branch) - emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); - jump = emit_jump_insn (gen_branch_false (L_end_loop_byte)); - add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + emit_label (L_loop_byte); - if (TARGET_SH2) - emit_insn (gen_dect (len, len)); - else - { - emit_insn (gen_addsi3 (len, len, GEN_INT (-1))); - emit_insn (gen_tstsi_t (len, len)); - } + emit_insn (gen_extendqisi2 (tmp1, addr1)); + emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 1)); - jump = emit_jump_insn (gen_branch_false (L_loop_byte)); - add_int_reg_note (jump, REG_BR_PROB, prob_likely); - /* end byte loop. */ + emit_insn (gen_cmpeqsi_t (tmp1, const0_rtx)); + jump = emit_jump_insn (gen_branch_false (L_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); - emit_label (L_end_loop_byte); + /* end loop. */ - if (! flag_delayed_branch) - emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); - emit_insn (gen_zero_extendqisi2 (tmp1, gen_lowpart (QImode, tmp1))); + emit_label (L_return); - emit_label (L_return); + emit_insn (gen_addsi3 (start_addr, start_addr, GEN_INT (1))); - emit_insn (gen_subsi3 (operands[0], tmp1, tmp2)); + emit_insn (gen_subsi3 (operands[0], current_addr, start_addr)); - return true; + return true; } |