From 2df9477bd7b3ca3acb238ae5253e1c2e69bfd512 Mon Sep 17 00:00:00 2001 From: bernds Date: Fri, 2 Jul 2010 16:22:33 +0000 Subject: [PATCH] PR target/42835 * config/arm/arm-modes.def (CC_NOTB): New mode. * config/arm/arm.c (get_arm_condition_code): Handle it. * config/arm/thumb2.md (thumb2_compare_scc): Delete pattern. * config/arm/arm.md (subsi3_compare0_c): New pattern. (compare_scc): Now a define_and_split. Add a number of extra splitters before it. testsuite/ PR target/42835 * gcc.target/arm/pr42835.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161725 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 +++ gcc/config/arm/arm-modes.def | 5 ++ gcc/config/arm/arm.c | 18 +++-- gcc/config/arm/arm.md | 126 +++++++++++++++++++++++++-------- gcc/config/arm/thumb2.md | 36 ---------- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/arm/pr42835.c | 12 ++++ 7 files changed, 142 insertions(+), 70 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr42835.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a398516..da53bdc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2010-07-02 Bernd Schmidt + + PR target/42835 + * config/arm/arm-modes.def (CC_NOTB): New mode. + * config/arm/arm.c (get_arm_condition_code): Handle it. + * config/arm/thumb2.md (thumb2_compare_scc): Delete pattern. + * config/arm/arm.md (subsi3_compare0_c): New pattern. + (compare_scc): Now a define_and_split. Add a number of extra + splitters before it. + 2010-07-02 Sandra Loosemore * config/arm/arm.c (neon_vdup_constant): Expand into canonical RTL diff --git a/gcc/config/arm/arm-modes.def b/gcc/config/arm/arm-modes.def index 813ce8e..55b98bc 100644 --- a/gcc/config/arm/arm-modes.def +++ b/gcc/config/arm/arm-modes.def @@ -34,6 +34,10 @@ ADJUST_FLOAT_FORMAT (HF, ((arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE) CCFPmode should be used with floating equalities. CC_NOOVmode should be used with SImode integer equalities. CC_Zmode should be used if only the Z flag is set correctly + CC_Cmode should be used if only the C flag is set correctly, after an + addition. + CC_NOTBmode should be used if only the C flag is set as a not-borrow + flag, after a subtraction. CC_Nmode should be used if only the N (sign) flag is set correctly CCmode should be used otherwise. */ @@ -53,6 +57,7 @@ CC_MODE (CC_DLTU); CC_MODE (CC_DGEU); CC_MODE (CC_DGTU); CC_MODE (CC_C); +CC_MODE (CC_NOTB); CC_MODE (CC_N); /* Vector modes. */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 92f19c3..fbdb90a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -16129,11 +16129,19 @@ get_arm_condition_code (rtx comparison) case CC_Cmode: switch (comp_code) - { - case LTU: return ARM_CS; - case GEU: return ARM_CC; - default: gcc_unreachable (); - } + { + case LTU: return ARM_CS; + case GEU: return ARM_CC; + default: gcc_unreachable (); + } + + case CC_NOTBmode: + switch (comp_code) + { + case LTU: return ARM_CC; + case GEU: return ARM_CS; + default: gcc_unreachable (); + } case CCmode: switch (comp_code) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 725d505..824022c 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1149,6 +1149,19 @@ [(set_attr "conds" "set")] ) +(define_insn "*subsi3_compare0_c" + [(set (reg:CC_NOTB CC_REGNUM) + (compare:CC_NOTB (match_operand:SI 1 "arm_rhs_operand" "r,I") + (match_operand:SI 2 "arm_rhs_operand" "rI,r"))) + (set (match_operand:SI 0 "s_register_operand" "=r,r") + (minus:SI (match_dup 1) (match_dup 2)))] + "TARGET_32BIT" + "@ + sub%.\\t%0, %1, %2 + rsb%.\\t%0, %2, %1" + [(set_attr "conds" "set")] +) + (define_expand "decscc" [(set (match_operand:SI 0 "s_register_operand" "=r,r") (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") @@ -9304,41 +9317,96 @@ (set_attr "length" "4,8")] ) -(define_insn "*compare_scc" +; A series of splitters for the compare_scc pattern below. Note that +; order is important. +(define_split + [(set (match_operand:SI 0 "s_register_operand" "") + (lt:SI (match_operand:SI 1 "s_register_operand" "") + (const_int 0))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_32BIT && reload_completed" + [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))]) + +(define_split + [(set (match_operand:SI 0 "s_register_operand" "") + (ge:SI (match_operand:SI 1 "s_register_operand" "") + (const_int 0))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_32BIT && reload_completed" + [(set (match_dup 0) (not:SI (match_dup 1))) + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))]) + +(define_split + [(set (match_operand:SI 0 "s_register_operand" "") + (eq:SI (match_operand:SI 1 "s_register_operand" "") + (const_int 0))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_32BIT && reload_completed" + [(parallel + [(set (reg:CC_NOTB CC_REGNUM) + (compare:CC_NOTB (const_int 1) (match_dup 1))) + (set (match_dup 0) + (minus:SI (const_int 1) (match_dup 1)))]) + (cond_exec (ltu:CC_NOTB (reg:CC_NOTB CC_REGNUM) (const_int 0)) + (set (match_dup 0) (const_int 0)))]) + +(define_split + [(set (match_operand:SI 0 "s_register_operand" "") + (ne:SI (match_operand:SI 1 "s_register_operand" "") + (match_operand:SI 2 "const_int_operand" ""))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_32BIT && reload_completed" + [(parallel + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]) + (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0)) + (set (match_dup 0) (const_int 1)))] +{ + operands[3] = GEN_INT (-INTVAL (operands[2])); +}) + +(define_split + [(set (match_operand:SI 0 "s_register_operand" "") + (ne:SI (match_operand:SI 1 "s_register_operand" "") + (match_operand:SI 2 "arm_add_operand" ""))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_32BIT && reload_completed" + [(parallel + [(set (reg:CC_NOOV CC_REGNUM) + (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2)) + (const_int 0))) + (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) + (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0)) + (set (match_dup 0) (const_int 1)))]) + +(define_insn_and_split "*compare_scc" [(set (match_operand:SI 0 "s_register_operand" "=r,r") (match_operator:SI 1 "arm_comparison_operator" [(match_operand:SI 2 "s_register_operand" "r,r") (match_operand:SI 3 "arm_add_operand" "rI,L")])) (clobber (reg:CC CC_REGNUM))] - "TARGET_ARM" - "* - if (operands[3] == const0_rtx) - { - if (GET_CODE (operands[1]) == LT) - return \"mov\\t%0, %2, lsr #31\"; - - if (GET_CODE (operands[1]) == GE) - return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; - - if (GET_CODE (operands[1]) == EQ) - return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; - } + "TARGET_32BIT" + "#" + "&& reload_completed" + [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3))) + (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0))) + (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))] +{ + rtx tmp1; + enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), + operands[2], operands[3]); + enum rtx_code rc = GET_CODE (operands[1]); - if (GET_CODE (operands[1]) == NE) - { - if (which_alternative == 1) - return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; - return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; - } - if (which_alternative == 1) - output_asm_insn (\"cmn\\t%2, #%n3\", operands); - else - output_asm_insn (\"cmp\\t%2, %3\", operands); - return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; - " - [(set_attr "conds" "clob") - (set_attr "length" "12")] -) + tmp1 = gen_rtx_REG (mode, CC_REGNUM); + + operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); + if (mode == CCFPmode || mode == CCFPEmode) + rc = reverse_condition_maybe_unordered (rc); + else + rc = reverse_condition (rc); + operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); +}) (define_insn "*cond_move" [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 3985183..ac275ad 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -599,42 +599,6 @@ (set_attr "length" "6,10")] ) -(define_insn "*thumb2_compare_scc" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (match_operator:SI 1 "arm_comparison_operator" - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_add_operand" "rI,L")])) - (clobber (reg:CC CC_REGNUM))] - "TARGET_THUMB2" - "* - if (operands[3] == const0_rtx) - { - if (GET_CODE (operands[1]) == LT) - return \"lsr\\t%0, %2, #31\"; - - if (GET_CODE (operands[1]) == GE) - return \"mvn\\t%0, %2\;lsr\\t%0, %0, #31\"; - - if (GET_CODE (operands[1]) == EQ) - return \"rsbs\\t%0, %2, #1\;it\\tcc\;movcc\\t%0, #0\"; - } - - if (GET_CODE (operands[1]) == NE) - { - if (which_alternative == 1) - return \"adds\\t%0, %2, #%n3\;it\\tne\;movne\\t%0, #1\"; - return \"subs\\t%0, %2, %3\;it\\tne\;movne\\t%0, #1\"; - } - if (which_alternative == 1) - output_asm_insn (\"cmn\\t%2, #%n3\", operands); - else - output_asm_insn (\"cmp\\t%2, %3\", operands); - return \"ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; - " - [(set_attr "conds" "clob") - (set_attr "length" "14")] -) - (define_insn "*thumb2_cond_move" [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") (if_then_else:SI (match_operator 3 "equality_operator" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f5b759b..2f7dd0c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-07-02 Bernd Schmidt + + PR target/42835 + * gcc.target/arm/pr42835.c: New test. + 2010-07-02 Paolo Carlini * g++.dg/template/crash98.C: Remove stray // from dg-error comment. diff --git a/gcc/testsuite/gcc.target/arm/pr42835.c b/gcc/testsuite/gcc.target/arm/pr42835.c new file mode 100644 index 0000000..71c51eb --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr42835.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-mthumb -Os" } */ +/* { dg-require-effective-target arm_thumb2_ok } */ + +int foo(int *p, int i) +{ + return( (i < 0 && *p == 1) + || (i > 0 && *p == 2) ); +} + +/* { dg-final { scan-assembler-times "movne\[\\t \]*r.,\[\\t \]*#" 1 } } */ +/* { dg-final { scan-assembler-times "moveq\[\\t \]*r.,\[\\t \]*#" 1 } } */ -- 2.7.4