diff options
Diffstat (limited to 'gcc-4.9/gcc/config/sh')
-rw-r--r-- | gcc-4.9/gcc/config/sh/predicates.md | 2 | ||||
-rw-r--r-- | gcc-4.9/gcc/config/sh/sh-mem.cc | 24 | ||||
-rw-r--r-- | gcc-4.9/gcc/config/sh/sh.c | 2 | ||||
-rw-r--r-- | gcc-4.9/gcc/config/sh/sh.md | 47 | ||||
-rw-r--r-- | gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc | 24 | ||||
-rw-r--r-- | gcc-4.9/gcc/config/sh/sh_treg_combine.cc | 49 | ||||
-rw-r--r-- | gcc-4.9/gcc/config/sh/sync.md | 18 |
7 files changed, 127 insertions, 39 deletions
diff --git a/gcc-4.9/gcc/config/sh/predicates.md b/gcc-4.9/gcc/config/sh/predicates.md index 73bb880..3af1f8a 100644 --- a/gcc-4.9/gcc/config/sh/predicates.md +++ b/gcc-4.9/gcc/config/sh/predicates.md @@ -398,7 +398,7 @@ (define_predicate "general_extend_operand" (match_code "subreg,reg,mem,truncate") { - if (GET_CODE (op) == TRUNCATE) + if (reload_completed && GET_CODE (op) == TRUNCATE) return arith_operand (op, mode); if (MEM_P (op) || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))) diff --git a/gcc-4.9/gcc/config/sh/sh-mem.cc b/gcc-4.9/gcc/config/sh/sh-mem.cc index 45af23a..e5ef165 100644 --- a/gcc-4.9/gcc/config/sh/sh-mem.cc +++ b/gcc-4.9/gcc/config/sh/sh-mem.cc @@ -1,5 +1,5 @@ /* Helper routines for memory move and comparison insns. - Copyright (C) 2013-2014 Free Software Foundation, Inc. + Copyright (C) 2013-2015 Free Software Foundation, Inc. This file is part of GCC. @@ -226,7 +226,7 @@ sh_expand_cmpstr (rtx *operands) emit_move_insn (tmp3, addr2); emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4)); - /*start long loop. */ + /* start long loop. */ emit_label (L_loop_long); emit_move_insn (tmp2, tmp3); @@ -335,7 +335,7 @@ sh_expand_cmpnstr (rtx *operands) rtx len = force_reg (SImode, operands[3]); int constp = CONST_INT_P (operands[3]); - /* Loop on a register count. */ + /* Loop on a register count. */ if (constp) { rtx tmp0 = gen_reg_rtx (SImode); @@ -364,7 +364,7 @@ sh_expand_cmpnstr (rtx *operands) add_int_reg_note (jump, REG_BR_PROB, prob_likely); } - /* word count. Do we have iterations ? */ + /* word count. Do we have iterations ? */ emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2))); /*start long loop. */ @@ -407,6 +407,7 @@ sh_expand_cmpnstr (rtx *operands) /* end loop. Reached max iterations. */ if (! sbytes) { + emit_insn (gen_subsi3 (operands[0], tmp1, tmp2)); jump = emit_jump_insn (gen_jump_compact (L_return)); emit_barrier_after (jump); } @@ -482,6 +483,13 @@ sh_expand_cmpnstr (rtx *operands) jump = emit_jump_insn (gen_jump_compact( L_end_loop_byte)); emit_barrier_after (jump); } + else + { + emit_insn (gen_cmpeqsi_t (len, const0_rtx)); + emit_move_insn (operands[0], const0_rtx); + jump = emit_jump_insn (gen_branch_true (L_return)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + } addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0); addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0); @@ -522,14 +530,14 @@ sh_expand_cmpnstr (rtx *operands) 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)); + emit_label (L_return); + return true; } -/* Emit code to perform a strlen +/* Emit code to perform a strlen. OPERANDS[0] is the destination. OPERANDS[1] is the string. @@ -568,7 +576,7 @@ sh_expand_strlen (rtx *operands) addr1 = adjust_automodify_address (addr1, SImode, current_addr, 0); - /*start long loop. */ + /* start long loop. */ emit_label (L_loop_long); /* tmp1 is aligned, OK to load. */ diff --git a/gcc-4.9/gcc/config/sh/sh.c b/gcc-4.9/gcc/config/sh/sh.c index 3d4553a..0679818 100644 --- a/gcc-4.9/gcc/config/sh/sh.c +++ b/gcc-4.9/gcc/config/sh/sh.c @@ -2957,7 +2957,7 @@ enum struct ashl_lshr_sequence { char insn_count; - char amount[6]; + signed char amount[6]; char clobbers_t; }; diff --git a/gcc-4.9/gcc/config/sh/sh.md b/gcc-4.9/gcc/config/sh/sh.md index ab1f0a5..d957e55 100644 --- a/gcc-4.9/gcc/config/sh/sh.md +++ b/gcc-4.9/gcc/config/sh/sh.md @@ -868,9 +868,9 @@ (define_insn "*cmp_div0s_0" [(set (reg:SI T_REG) - (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") + (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand" "%r") (const_int 31)) - (ge:SI (match_operand:SI 1 "arith_reg_operand") + (ge:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0))))] "TARGET_SH1" "div0s %0,%1" @@ -4563,6 +4563,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -4803,6 +4809,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -4896,6 +4908,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -4995,6 +5013,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -5069,6 +5093,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -5263,6 +5293,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -6295,10 +6331,9 @@ label: }) (define_expand "extendqihi2" - [(set (match_operand:HI 0 "arith_reg_dest" "") - (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))] - "" - "") + [(set (match_operand:HI 0 "arith_reg_dest") + (sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))] + "TARGET_SH1") (define_insn "*extendqihi2_compact_reg" [(set (match_operand:HI 0 "arith_reg_dest" "=r") diff --git a/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc b/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc index 313e5b5..3791cc7 100644 --- a/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc +++ b/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc @@ -111,7 +111,7 @@ private: // Given a start insn and its basic block, recursively determine all // possible ccreg values in all basic block paths that can lead to the // start insn. - void find_last_ccreg_values (rtx start_insn, basic_block bb, + bool find_last_ccreg_values (rtx start_insn, basic_block bb, std::vector<ccreg_value>& values_out, std::vector<basic_block>& prev_visited_bb) const; @@ -226,8 +226,8 @@ sh_optimize_sett_clrt::execute (void) ccreg_values.clear (); visited_bbs.clear (); - find_last_ccreg_values (PREV_INSN (i), bb, ccreg_values, - visited_bbs); + bool ok = find_last_ccreg_values (PREV_INSN (i), bb, ccreg_values, + visited_bbs); log_msg ("number of ccreg values collected: %u\n", (unsigned int)ccreg_values.size ()); @@ -235,7 +235,7 @@ sh_optimize_sett_clrt::execute (void) // If all the collected values are equal and are equal to the // constant value of the setcc insn, the setcc insn can be // removed. - if (all_ccreg_values_equal (ccreg_values) + if (ok && all_ccreg_values_equal (ccreg_values) && rtx_equal_p (ccreg_values.front ().value, setcc_val)) { log_msg ("all values are "); @@ -309,7 +309,7 @@ sh_optimize_sett_clrt gcc_unreachable (); } -void +bool sh_optimize_sett_clrt ::find_last_ccreg_values (rtx start_insn, basic_block bb, std::vector<ccreg_value>& values_out, @@ -348,7 +348,7 @@ sh_optimize_sett_clrt log_msg ("\n"); values_out.push_back (v); - return; + return true; } if (any_condjump_p (i) && onlyjump_p (i) && !prev_visited_bb.empty ()) @@ -372,7 +372,7 @@ sh_optimize_sett_clrt log_msg ("\n"); values_out.push_back (v); - return; + return true; } } @@ -393,10 +393,14 @@ sh_optimize_sett_clrt for (edge_iterator ei = ei_start (bb->preds); !ei_end_p (ei); ei_next (&ei)) { + if (ei_edge (ei)->flags & EDGE_COMPLEX) + log_return (false, "aborting due to complex edge\n"); + basic_block pred_bb = ei_edge (ei)->src; pred_bb_count += 1; - find_last_ccreg_values (BB_END (pred_bb), pred_bb, values_out, - prev_visited_bb); + if (!find_last_ccreg_values (BB_END (pred_bb), pred_bb, values_out, + prev_visited_bb)) + return false; } prev_visited_bb.pop_back (); @@ -419,6 +423,8 @@ sh_optimize_sett_clrt values_out.push_back (v); } + + return true; } bool diff --git a/gcc-4.9/gcc/config/sh/sh_treg_combine.cc b/gcc-4.9/gcc/config/sh/sh_treg_combine.cc index e736040..38e2803 100644 --- a/gcc-4.9/gcc/config/sh/sh_treg_combine.cc +++ b/gcc-4.9/gcc/config/sh/sh_treg_combine.cc @@ -78,14 +78,17 @@ Example 1) In [bb 4] elimination of the comparison would require inversion of the branch condition and compensation of other BBs. -Instead an inverting reg-move can be used: +Instead the comparison in [bb 3] can be replaced with the comparison in [bb 5] +by using a reg-reg move. In [bb 4] a logical not is used to compensate the +inverted condition. [bb 3] (set (reg:SI 167) (reg:SI 173)) -> bb 5 [BB 4] -(set (reg:SI 167) (not:SI (reg:SI 177))) +(set (reg:SI 147 t) (eq:SI (reg:SI 177) (const_int 0))) +(set (reg:SI 167) (reg:SI 147 t)) -> bb 5 [bb 5] @@ -214,9 +217,9 @@ In order to handle cases such as above the RTL pass does the following: and replace the comparisons in the BBs with reg-reg copies to get the operands in place (create new pseudo regs). - - If the cstores differ, try to apply the special case - (eq (reg) (const_int 0)) -> inverted = (not (reg)). - for the subordinate cstore types and eliminate the dominating ones. + - If the cstores differ and the comparison is a test against zero, + use reg-reg copies for the dominating cstores and logical not cstores + for the subordinate cstores. - If the comparison types in the BBs are not the same, or the first approach doesn't work out for some reason, try to eliminate the comparison before the @@ -558,7 +561,8 @@ private: bool can_extend_ccreg_usage (const bb_entry& e, const cbranch_trace& trace) const; - // Create an insn rtx that is a negating reg move (not operation). + // Create an insn rtx that performs a logical not (test != 0) on the src_reg + // and stores the result in dst_reg. rtx make_not_reg_insn (rtx dst_reg, rtx src_reg) const; // Create an insn rtx that inverts the ccreg. @@ -892,12 +896,32 @@ sh_treg_combine::can_remove_comparison (const bb_entry& e, rtx sh_treg_combine::make_not_reg_insn (rtx dst_reg, rtx src_reg) const { - // This will to go through expanders and may output multiple insns - // for multi-word regs. + // On SH we can do only SImode and DImode comparisons. + if (! (GET_MODE (src_reg) == SImode || GET_MODE (src_reg) == DImode)) + return NULL; + + // On SH we can store the ccreg into an SImode or DImode reg only. + if (! (GET_MODE (dst_reg) == SImode || GET_MODE (dst_reg) == DImode)) + return NULL; + start_sequence (); - expand_simple_unop (GET_MODE (dst_reg), NOT, src_reg, dst_reg, 0); + + emit_insn (gen_rtx_SET (VOIDmode, m_ccreg, + gen_rtx_fmt_ee (EQ, SImode, src_reg, const0_rtx))); + + if (GET_MODE (dst_reg) == SImode) + emit_move_insn (dst_reg, m_ccreg); + else if (GET_MODE (dst_reg) == DImode) + { + emit_move_insn (gen_lowpart (SImode, dst_reg), m_ccreg); + emit_move_insn (gen_highpart (SImode, dst_reg), const0_rtx); + } + else + gcc_unreachable (); + rtx i = get_insns (); end_sequence (); + return i; } @@ -1080,7 +1104,12 @@ sh_treg_combine::try_combine_comparisons (cbranch_trace& trace, // There is one special case though, where an integer comparison // (eq (reg) (const_int 0)) // can be inverted with a sequence - // (eq (not (reg)) (const_int 0)) + // (set (t) (eq (reg) (const_int 0)) + // (set (reg) (t)) + // (eq (reg) (const_int 0)) + // + // FIXME: On SH2A it might be better to use the nott insn in this case, + // i.e. do the try_eliminate_cstores approach instead. if (inv_cstore_count != 0 && cstore_count != 0) { if (make_not_reg_insn (comp_op0, comp_op0) == NULL_RTX) diff --git a/gcc-4.9/gcc/config/sh/sync.md b/gcc-4.9/gcc/config/sh/sync.md index a0a22a1..a3acaac 100644 --- a/gcc-4.9/gcc/config/sh/sync.md +++ b/gcc-4.9/gcc/config/sh/sync.md @@ -466,6 +466,7 @@ (set (mem:SI (match_dup 1)) (unspec:SI [(match_operand:SI 2 "arith_operand" "rI08")] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" @@ -484,6 +485,7 @@ (set (mem:QIHI (match_dup 1)) (unspec:QIHI [(match_operand:QIHI 2 "register_operand" "r")] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -617,6 +619,7 @@ [(FETCHOP:SI (mem:SI (match_dup 1)) (match_operand:SI 2 "<fetchop_predicate>" "<fetchop_constraint>"))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" @@ -637,6 +640,7 @@ [(FETCHOP:QIHI (mem:QIHI (match_dup 1)) (match_operand:QIHI 2 "<fetchop_predicate>" "<fetchop_constraint>"))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -784,6 +788,7 @@ [(not:SI (and:SI (mem:SI (match_dup 1)) (match_operand:SI 2 "logical_operand" "rK08")))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" @@ -805,6 +810,7 @@ [(not:QIHI (and:QIHI (mem:QIHI (match_dup 1)) (match_operand:QIHI 2 "logical_operand" "rK08")))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -903,7 +909,7 @@ " and %0,%3" "\n" " not %3,%3" "\n" " mov.<bwl> %3,@%1" "\n" - " stc %4,sr"; + " ldc %4,sr"; } [(set_attr "length" "20")]) @@ -960,7 +966,8 @@ (set (mem:SI (match_dup 1)) (unspec:SI [(FETCHOP:SI (mem:SI (match_dup 1)) (match_dup 2))] - UNSPEC_ATOMIC))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" { @@ -980,6 +987,7 @@ (unspec:QIHI [(FETCHOP:QIHI (mem:QIHI (match_dup 1)) (match_dup 2))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -1124,7 +1132,8 @@ (set (mem:SI (match_dup 1)) (unspec:SI [(not:SI (and:SI (mem:SI (match_dup 1)) (match_dup 2)))] - UNSPEC_ATOMIC))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" { @@ -1145,6 +1154,7 @@ (unspec:QIHI [(not:QIHI (and:QIHI (mem:QIHI (match_dup 1)) (match_dup 2)))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -1353,7 +1363,7 @@ " ldc r0,sr" "\n" " mov.b @%0,r0" "\n" " mov.b %1,@%0" "\n" - " stc %2,sr" "\n" + " ldc %2,sr" "\n" " tst r0,r0"; } [(set_attr "length" "16")]) |