diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 78 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr49468-di.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr49468-si.c | 1 |
5 files changed, 114 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c0242a9..eabe45f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2012-03-02 Oleg Endo <olegendo@gcc.gnu.org> + PR target/49486 + * config/sh/sh.md (negdi2): Add TARGET_SH1 condition. + (absdi2): New expander. + (*absdi2, *negabsdi2, negdi_cond): New insns and splits. + +2012-03-02 Oleg Endo <olegendo@gcc.gnu.org> + * config/sh/sync.md (atomic_exchange<mode>): New expander. (atomic_exchange<mode>_soft): New insn. diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index b356584..56a0f3c 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -4411,7 +4411,7 @@ label: [(set (match_operand:DI 0 "arith_reg_dest" "") (neg:DI (match_operand:DI 1 "arith_reg_operand" ""))) (clobber (reg:SI T_REG))] - "" + "TARGET_SH1" "") (define_insn_and_split "*negdi2" @@ -4531,6 +4531,82 @@ label: [(set_attr "type" "arith") ;; poor approximation (set_attr "length" "4")]) +(define_expand "absdi2" + [(set (match_operand:DI 0 "arith_reg_dest" "") + (abs:DI (match_operand:DI 1 "arith_reg_operand" ""))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "") + +(define_insn_and_split "*absdi2" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (abs:DI (match_operand:DI 1 "arith_reg_operand" "r")))] + "TARGET_SH1" + "#" + "&& reload_completed" + [(const_int 0)] +{ + int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0); + rtx high_src = operand_subword (operands[1], high_word, 0, DImode); + emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); + emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1], + const1_rtx)); + DONE; +}) + +(define_insn_and_split "*negabsdi2" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (neg:DI (abs:DI (match_operand:DI 1 "arith_reg_operand" "r"))))] + "TARGET_SH1" + "#" + "&& reload_completed" + [(const_int 0)] +{ + int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0); + rtx high_src = operand_subword (operands[1], high_word, 0, DImode); + + emit_insn (gen_cmpgesi_t (high_src, const0_rtx)); + emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1], + const0_rtx)); + DONE; +}) + +(define_insn_and_split "negdi_cond" + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") + (if_then_else:DI (eq:SI (reg:SI T_REG) + (match_operand:SI 3 "const_int_operand" "M,N")) + (match_operand:DI 1 "arith_reg_operand" "r,r") + (neg:DI (match_operand:DI 2 "arith_reg_operand" "1,1"))))] + "TARGET_SH1" + "#" + "TARGET_SH1" + [(const_int 0)] +{ + int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1); + int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0); + + rtx low_src = operand_subword (operands[1], low_word, 0, DImode); + rtx high_src = operand_subword (operands[1], high_word, 0, DImode); + + rtx low_dst = operand_subword (operands[0], low_word, 1, DImode); + rtx high_dst = operand_subword (operands[0], high_word, 1, DImode); + + rtx skip_neg_label = gen_label_rtx (); + + emit_insn (gen_movsi (low_dst, low_src)); + emit_insn (gen_movsi (high_dst, high_src)); + + emit_jump_insn (INTVAL (operands[3]) + ? gen_branch_true (skip_neg_label) + : gen_branch_false (skip_neg_label)); + + if (!INTVAL (operands[3])) + emit_insn (gen_clrt ()); + + emit_insn (gen_negc (low_dst, low_src)); + emit_label_after (skip_neg_label, emit_insn (gen_negc (high_dst, high_src))); + DONE; +}) ;; ------------------------------------------------------------------------- ;; Zero extension instructions diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4868f33..9c4fc1a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-03-02 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/49486 + * gcc.target/sh/pr49468-si.c: Skip unsupported test for SH64. + * gcc.target/sh/pr49468-di.c: New. + 2012-03-02 Maxim Kuvyrkov <maxim@codesourcery.com> * gcc.dg/graphite/pr50561.c: Update. diff --git a/gcc/testsuite/gcc.target/sh/pr49468-di.c b/gcc/testsuite/gcc.target/sh/pr49468-di.c new file mode 100644 index 0000000..86fe21d --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr49468-di.c @@ -0,0 +1,23 @@ +/* Check that 64 bit integer abs is generated as negc instruction pairs + and conditional branch instead of default branch-free code. */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-final { scan-assembler-times "negc" 4 } } */ + + +/* Normal integer absolute value. */ +long long +abs_0 (long long i) +{ + return (i < 0) ? -i : i; +} + +/* Negated integer absolute value. + The generated code should be the same, except that the branch + condition is inverted. */ +long long +abs_1 (long long i) +{ + return (i > 0) ? -i : i; +} diff --git a/gcc/testsuite/gcc.target/sh/pr49468-si.c b/gcc/testsuite/gcc.target/sh/pr49468-si.c index 69fbe23..e581b2a 100644 --- a/gcc/testsuite/gcc.target/sh/pr49468-si.c +++ b/gcc/testsuite/gcc.target/sh/pr49468-si.c @@ -1,5 +1,6 @@ /* Check that 32 bit integer abs is generated as neg instruction and conditional branch instead of default branch-free code. */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ /* { dg-do compile { target "sh*-*-*" } } */ /* { dg-options "-O1" } */ /* { dg-final { scan-assembler-times "neg" 2 } } */ |