re PR rtl-optimization/42835 (Missed merging common code sequence at the end of two...
authorBernd Schmidt <bernds@codesourcery.com>
Fri, 2 Jul 2010 16:22:33 +0000 (16:22 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Fri, 2 Jul 2010 16:22:33 +0000 (16:22 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm-modes.def
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/arm/thumb2.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/pr42835.c [new file with mode: 0644]

index a398516..da53bdc 100644 (file)
@@ -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
index 813ce8e..55b98bc 100644 (file)
@@ -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.  */
index 92f19c3..fbdb90a 100644 (file)
@@ -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)
index 725d505..824022c 100644 (file)
   [(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")
    (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")
index 3985183..ac275ad 100644 (file)
    (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"
index f5b759b..2f7dd0c 100644 (file)
@@ -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 (file)
index 0000000..71c51eb
--- /dev/null
@@ -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 } } */