aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2010-07-02 16:22:33 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2010-07-02 16:22:33 +0000
commit18e8200f7082b15957ee05829ce51a06c381b378 (patch)
tree3e2175e4e860e041e9dd2980eda39ad668e981e4
parentfaeb4ee3aac0ece0f8619ba8c3a2908c6ed7b9c1 (diff)
downloadgcc-18e8200f7082b15957ee05829ce51a06c381b378.zip
gcc-18e8200f7082b15957ee05829ce51a06c381b378.tar.gz
gcc-18e8200f7082b15957ee05829ce51a06c381b378.tar.bz2
re PR rtl-optimization/42835 (Missed merging common code sequence at the end of two basic blocks)
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. From-SVN: r161725
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/arm/arm-modes.def5
-rw-r--r--gcc/config/arm/arm.c18
-rw-r--r--gcc/config/arm/arm.md126
-rw-r--r--gcc/config/arm/thumb2.md36
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/arm/pr42835.c12
7 files changed, 142 insertions, 70 deletions
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 <bernds@codesourcery.com>
+
+ 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 <sandra@codesourcery.com>
* 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 <bernds@codesourcery.com>
+
+ PR target/42835
+ * gcc.target/arm/pr42835.c: New test.
+
2010-07-02 Paolo Carlini <paolo.carlini@oracle.com>
* 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 } } */