[01/29,arm] Rip out DImode addition and subtraction splits.
diff mbox series

Message ID 20191018194900.34795-2-Richard.Earnshaw@arm.com
State New
Headers show
Series
  • Rewrite DImode arithmetic support
Related show

Commit Message

Richard Earnshaw (lists) Oct. 18, 2019, 7:48 p.m. UTC
The first step towards early splitting of addition and subtraction at
DImode is to rip out the old patterns that are designed to propagate
DImode through the RTL optimization passes and the do late splitting.

This patch does cause some code size regressions, but it should still
execute correctly.  We will progressively add back the optimizations
we had here in later patches.

A small number of tests in the Arm-specific testsuite do fail as a
result of this patch, but that's to be expected, since the
optimizations they are looking for have just been removed.  I've kept
the tests, but XFAILed them for now.

One small technical change is also done in this patch as part of the
cleanup: the uaddv<mode>4 expander is changed to use LTU as the branch
comparison.  This eliminates the need for CC_Cmode to recognize
somewhat bogus equality constraints.

gcc:
	* arm.md (adddi3): Only accept register operands.
	(arm_adddi3): Convert to simple insn with no split.  Do not accept
	constants.
	(adddi_sesidi_di): Delete patern.
	(adddi_zesidi_di): Likewise.
	(uaddv<mode>4): Use LTU as condition for branch.
	(adddi3_compareV): Convert to simple insn with no split.
	(addsi3_compareV_upper): Delete pattern.
	(adddi3_compareC): Convert to simple insn with no split.  Correct
	flags setting expression.
	(addsi3_compareC_upper): Delete pattern.
	(addsi3_compareC): Correct flags setting expression.
	(subdi3_compare1): Convert to simple insn with no split.
	(subsi3_carryin_compare): Delete pattern.
	(arm_subdi3): Convert to simple insn with no split.
	(subdi_zesidi): Delete pattern.
	(subdi_di_sesidi): Delete pattern.
	(subdi_zesidi_di): Delete pattern.
	(subdi_sesidi_di): Delete pattern.
	(subdi_zesidi_zesidi): Delete pattern.
	(negvdi3): Use s_register_operand.
	(negdi2_compare): Convert to simple insn with no split.
	(negdi2_insn): Likewise.
	(negsi2_carryin_compare): Delete pattern.
	(negdi_zero_extendsidi): Delete pattern.
	(arm_cmpdi_insn): Convert to simple insn with no split.
	(negdi2): Don't call gen_negdi2_neon.
	* config/arm/neon.md (adddi3_neon): Delete pattern.
	(subdi3_neon): Delete pattern.
	(negdi2_neon): Delete pattern.
	(splits for negdi2_neon): Delete splits.

testsuite:
	* gcc.target/arm/negdi-3.c: Add XFAILS.
	* gcc.target/arm/pr3447-1.c: Likewise.
	* gcc.target/arm/pr3447-3.c: Likewise.
	* gcc.target/arm/pr3447-4.c: Likewise.
---
 gcc/config/arm/arm.c                     |   2 -
 gcc/config/arm/arm.md                    | 569 ++---------------------
 gcc/testsuite/gcc.target/arm/negdi-3.c   |   8 +-
 gcc/testsuite/gcc.target/arm/pr53447-1.c |   2 +-
 gcc/testsuite/gcc.target/arm/pr53447-3.c |   2 +-
 gcc/testsuite/gcc.target/arm/pr53447-4.c |   2 +-
 6 files changed, 56 insertions(+), 529 deletions(-)

Patch
diff mbox series

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index ba330470141..41567af1869 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -23581,8 +23581,6 @@  maybe_get_arm_condition_code (rtx comparison)
 	{
 	case LTU: return ARM_CS;
 	case GEU: return ARM_CC;
-	case NE: return ARM_CS;
-	case EQ: return ARM_CC;
 	default: return ARM_NV;
 	}
 
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index f861c72ccfc..241ba97c4ba 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -437,7 +437,7 @@  (define_expand "adddi3"
  [(parallel
    [(set (match_operand:DI           0 "s_register_operand")
 	  (plus:DI (match_operand:DI 1 "s_register_operand")
-	           (match_operand:DI 2 "arm_adddi_operand")))
+	           (match_operand:DI 2 "s_register_operand")))
     (clobber (reg:CC CC_REGNUM))])]
   "TARGET_EITHER"
   "
@@ -446,87 +446,13 @@  (define_expand "adddi3"
   "
 )
 
-(define_insn_and_split "*arm_adddi3"
-  [(set (match_operand:DI          0 "arm_general_register_operand" "=&r,&r,&r,&r,&r")
-	(plus:DI (match_operand:DI 1 "arm_general_register_operand" "%0, 0, r, 0, r")
-		 (match_operand:DI 2 "arm_general_adddi_operand"    "r,  0, r, Dd, Dd")))
+(define_insn "*arm_adddi3"
+  [(set (match_operand:DI 0 "s_register_operand"  "=&r,&r,&r")
+	(plus:DI (match_operand:DI 1 "s_register_operand" " %0,0,r")
+		 (match_operand:DI 2 "s_register_operand" " r,0,r")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_32BIT"
-  "#"
-  "TARGET_32BIT"
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-				 (match_dup 1)))
-	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
-			       (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
-(define_insn_and_split "*adddi_sesidi_di"
-  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
-	(plus:DI (sign_extend:DI
-		  (match_operand:SI 2 "s_register_operand" "r,r"))
-		 (match_operand:DI 1 "s_register_operand" "0,r")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "#"
-  "TARGET_32BIT && reload_completed"
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-				 (match_dup 1)))
-	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
-						     (const_int 31))
-					(match_dup 4))
-			       (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
-(define_insn_and_split "*adddi_zesidi_di"
-  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
-	(plus:DI (zero_extend:DI
-		  (match_operand:SI 2 "s_register_operand" "r,r"))
-		 (match_operand:DI 1 "s_register_operand" "0,r")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "#"
-  "TARGET_32BIT && reload_completed"
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-				 (match_dup 1)))
-	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
-			       (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
+  "adds\\t%Q0, %Q1, %Q2;adc\\t%R0, %R1, %R2"
   [(set_attr "conds" "clob")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
@@ -553,7 +479,7 @@  (define_expand "uaddv<mode>4"
   "TARGET_32BIT"
 {
   emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
-  arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
+  arm_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
 
   DONE;
 })
@@ -636,44 +562,17 @@  (define_insn_and_split "*arm_addsi3"
  ]
 )
 
-(define_insn_and_split "adddi3_compareV"
+(define_insn "adddi3_compareV"
   [(set (reg:CC_V CC_REGNUM)
 	(ne:CC_V
 	  (plus:TI
-	    (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
-	    (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
+	    (sign_extend:TI (match_operand:DI 1 "s_register_operand" "r"))
+	    (sign_extend:TI (match_operand:DI 2 "s_register_operand" "r")))
 	  (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
-   (set (match_operand:DI 0 "register_operand" "=&r")
+   (set (match_operand:DI 0 "s_register_operand" "=&r")
 	(plus:DI (match_dup 1) (match_dup 2)))]
   "TARGET_32BIT"
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-				 (match_dup 1)))
-	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (parallel [(set (reg:CC_V CC_REGNUM)
-		   (ne:CC_V
-		    (plus:DI (plus:DI
-			      (sign_extend:DI (match_dup 4))
-			      (sign_extend:DI (match_dup 5)))
-			     (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
-		    (plus:DI (sign_extend:DI
-			      (plus:SI (match_dup 4) (match_dup 5)))
-			     (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
-	     (set (match_dup 3) (plus:SI (plus:SI
-					  (match_dup 4) (match_dup 5))
-					 (ltu:SI (reg:CC_C CC_REGNUM)
-						 (const_int 0))))])]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[5] = gen_highpart (SImode, operands[2]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
+  "adds\\t%Q0, %Q1, %Q2;adcs\\t%R0, %R1, %R2"
  [(set_attr "conds" "set")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
@@ -694,99 +593,27 @@  (define_insn "addsi3_compareV"
    (set_attr "type" "alus_sreg")]
 )
 
-(define_insn "*addsi3_compareV_upper"
-  [(set (reg:CC_V CC_REGNUM)
-	(ne:CC_V
-	  (plus:DI
-	   (plus:DI
-	    (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-	    (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
-	   (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
-	  (plus:DI (sign_extend:DI
-		    (plus:SI (match_dup 1) (match_dup 2)))
-		   (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
-   (set (match_operand:SI 0 "register_operand" "=r")
-	(plus:SI
-	 (plus:SI (match_dup 1) (match_dup 2))
-	 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
-  "TARGET_32BIT"
-  "adcs%?\\t%0, %1, %2"
-  [(set_attr "conds" "set")
-   (set_attr "type" "adcs_reg")]
-)
-
-(define_insn_and_split "adddi3_compareC"
+(define_insn "adddi3_compareC"
   [(set (reg:CC_C CC_REGNUM)
-	(ne:CC_C
-	  (plus:TI
-	    (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
-	    (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
-	  (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
+	(compare:CC_C
+	  (plus:DI
+	    (match_operand:DI 1 "register_operand" "r")
+	    (match_operand:DI 2 "register_operand" "r"))
+	  (match_dup 1)))
    (set (match_operand:DI 0 "register_operand" "=&r")
 	(plus:DI (match_dup 1) (match_dup 2)))]
   "TARGET_32BIT"
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-				 (match_dup 1)))
-	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (parallel [(set (reg:CC_C CC_REGNUM)
-		   (ne:CC_C
-		    (plus:DI (plus:DI
-			      (zero_extend:DI (match_dup 4))
-			      (zero_extend:DI (match_dup 5)))
-			     (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
-		    (plus:DI (zero_extend:DI
-			      (plus:SI (match_dup 4) (match_dup 5)))
-			     (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
-	     (set (match_dup 3) (plus:SI
-				 (plus:SI (match_dup 4) (match_dup 5))
-				 (ltu:SI (reg:CC_C CC_REGNUM)
-					 (const_int 0))))])]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[5] = gen_highpart (SImode, operands[2]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
+  "adds\\t%Q0, %Q1, %Q2;adcs\\t%R0, %R1, %R2"
  [(set_attr "conds" "set")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
 )
 
-(define_insn "*addsi3_compareC_upper"
-  [(set (reg:CC_C CC_REGNUM)
-	(ne:CC_C
-	  (plus:DI
-	   (plus:DI
-	    (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-	    (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
-	   (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
-	  (plus:DI (zero_extend:DI
-		    (plus:SI (match_dup 1) (match_dup 2)))
-		   (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
-   (set (match_operand:SI 0 "register_operand" "=r")
-	(plus:SI
-	 (plus:SI (match_dup 1) (match_dup 2))
-	 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
-  "TARGET_32BIT"
-  "adcs%?\\t%0, %1, %2"
-  [(set_attr "conds" "set")
-   (set_attr "type" "adcs_reg")]
-)
-
 (define_insn "addsi3_compareC"
    [(set (reg:CC_C CC_REGNUM)
-	 (ne:CC_C
-	  (plus:DI
-	   (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-	   (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
-	  (zero_extend:DI
-	   (plus:SI (match_dup 1) (match_dup 2)))))
+	 (compare:CC_C (plus:SI (match_operand:SI 1 "register_operand" "r")
+				(match_operand:SI 2 "register_operand" "r"))
+		       (match_dup 1)))
     (set (match_operand:SI 0 "register_operand" "=r")
 	 (plus:SI (match_dup 1) (match_dup 2)))]
   "TARGET_32BIT"
@@ -1094,31 +921,15 @@  (define_expand "usubv<mode>4"
   DONE;
 })
 
-(define_insn_and_split "subdi3_compare1"
+(define_insn "subdi3_compare1"
   [(set (reg:CC CC_REGNUM)
 	(compare:CC
-	  (match_operand:DI 1 "register_operand" "r")
-	  (match_operand:DI 2 "register_operand" "r")))
-   (set (match_operand:DI 0 "register_operand" "=&r")
+	  (match_operand:DI 1 "s_register_operand" "r")
+	  (match_operand:DI 2 "s_register_operand" "r")))
+   (set (match_operand:DI 0 "s_register_operand" "=&r")
 	(minus:DI (match_dup 1) (match_dup 2)))]
   "TARGET_32BIT"
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 1) (match_dup 2)))
-	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
-   (parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 4) (match_dup 5)))
-	     (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
-			       (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[5] = gen_highpart (SImode, operands[2]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-   }
+  "subs\\t%Q0, %Q1, %Q2;sbcs\\t%R0, %R1, %R2"
   [(set_attr "conds" "set")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
@@ -1175,49 +986,6 @@  (define_insn "*subsi3_carryin_const0"
    (set_attr "type" "adc_imm")]
 )
 
-(define_insn "*subsi3_carryin_compare"
-  [(set (reg:CC CC_REGNUM)
-	(compare:CC (match_operand:SI 1 "s_register_operand" "r")
-		    (match_operand:SI 2 "s_register_operand" "r")))
-   (set (match_operand:SI 0 "s_register_operand" "=r")
-	(minus:SI (minus:SI (match_dup 1) (match_dup 2))
-		  (match_operand:SI 3 "arm_borrow_operation" "")))]
-  "TARGET_32BIT"
-  "sbcs\\t%0, %1, %2"
-  [(set_attr "conds" "set")
-   (set_attr "type" "adcs_reg")]
-)
-
-(define_insn "*subsi3_carryin_compare_const"
-  [(set (reg:CC CC_REGNUM)
-	(compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
-		    (match_operand:SI 2 "const_int_I_operand" "I")))
-   (set (match_operand:SI 0 "s_register_operand" "=r")
-	(minus:SI (plus:SI
-		   (match_dup 1)
-		   (match_operand:SI 3 "arm_neg_immediate_operand" "L"))
-		  (match_operand:SI 4 "arm_borrow_operation" "")))]
-  "TARGET_32BIT
-   && (INTVAL (operands[2])
-       == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
-  "sbcs\\t%0, %1, #%n3"
-  [(set_attr "conds" "set")
-   (set_attr "type" "adcs_imm")]
-)
-
-(define_insn "*subsi3_carryin_compare_const0"
-  [(set (reg:CC CC_REGNUM)
-	(compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
-		    (const_int 0)))
-   (set (match_operand:SI 0 "s_register_operand" "=r")
-	(minus:SI (match_dup 1)
-		  (match_operand:SI 2 "arm_borrow_operation" "")))]
-  "TARGET_32BIT"
-  "sbcs\\t%0, %1, #0"
-  [(set_attr "conds" "set")
-   (set_attr "type" "adcs_imm")]
-)
-
 (define_insn "*subsi3_carryin_shift"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
 	(minus:SI (minus:SI
@@ -1286,166 +1054,19 @@  (define_expand "subdi3"
  [(parallel
    [(set (match_operand:DI            0 "s_register_operand")
 	  (minus:DI (match_operand:DI 1 "s_register_operand")
-	            (match_operand:DI 2 "s_register_operand")))
+		    (match_operand:DI 2 "s_register_operand")))
     (clobber (reg:CC CC_REGNUM))])]
   "TARGET_EITHER"
   "
 ")
 
-(define_insn_and_split "*arm_subdi3"
-  [(set (match_operand:DI           0 "arm_general_register_operand" "=&r,&r,&r")
+(define_insn "*arm_subdi3"
+  [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r")
 	(minus:DI (match_operand:DI 1 "arm_general_register_operand" "0,r,0")
 		  (match_operand:DI 2 "arm_general_register_operand" "r,0,0")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_32BIT"
-  "#"  ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
-  "TARGET_32BIT"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 1) (match_dup 2)))
-	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
-			       (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[5] = gen_highpart (SImode, operands[2]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-   }
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
-(define_insn_and_split "*subdi_di_zesidi"
-  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
-	(minus:DI (match_operand:DI 1 "s_register_operand"  "0,r")
-		  (zero_extend:DI
-		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "#"   ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 1) (match_dup 2)))
-	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (minus:SI (match_dup 4)
-				(ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-   }
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
-(define_insn_and_split "*subdi_di_sesidi"
-  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
-	(minus:DI (match_operand:DI  1 "s_register_operand"  "0,r")
-		  (sign_extend:DI
-		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "#"   ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 1) (match_dup 2)))
-	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
-                                         (ashiftrt:SI (match_dup 2)
-                                                      (const_int 31)))
-                                (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-  }
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
-(define_insn_and_split "*subdi_zesidi_di"
-  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
-	(minus:DI (zero_extend:DI
-		   (match_operand:SI 2 "s_register_operand"  "r,r"))
-		  (match_operand:DI  1 "s_register_operand" "0,r")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_ARM"
-  "#"   ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
-        ; is equivalent to:
-        ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 2) (match_dup 1)))
-	      (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
-   (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
-			       (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-  }
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
-(define_insn_and_split "*subdi_sesidi_di"
-  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
-	(minus:DI (sign_extend:DI
-		   (match_operand:SI 2 "s_register_operand"   "r,r"))
-		  (match_operand:DI  1 "s_register_operand"  "0,r")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_ARM"
-  "#"   ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
-        ; is equivalent to:
-        ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 2) (match_dup 1)))
-	      (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
-   (set (match_dup 3) (minus:SI (minus:SI
-                                (ashiftrt:SI (match_dup 2)
-                                             (const_int 31))
-                                (match_dup 4))
-			       (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-  }
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
-(define_insn_and_split "*subdi_zesidi_zesidi"
-  [(set (match_operand:DI            0 "s_register_operand" "=r")
-	(minus:DI (zero_extend:DI
-		   (match_operand:SI 1 "s_register_operand"  "r"))
-		  (zero_extend:DI
-		   (match_operand:SI 2 "s_register_operand"  "r"))))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "#"   ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 1) (match_dup 2)))
-	      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
-			       (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-       operands[3] = gen_highpart (SImode, operands[0]);
-       operands[0] = gen_lowpart (SImode, operands[0]);
-  }
+  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
   [(set_attr "conds" "clob")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
@@ -4035,8 +3656,8 @@  (define_expand "negvsi3"
 })
 
 (define_expand "negvdi3"
-  [(match_operand:DI 0 "register_operand")
-   (match_operand:DI 1 "register_operand")
+  [(match_operand:DI 0 "s_register_operand")
+   (match_operand:DI 1 "s_register_operand")
    (match_operand 2 "")]
   "TARGET_ARM"
 {
@@ -4047,34 +3668,19 @@  (define_expand "negvdi3"
 })
 
 
-(define_insn_and_split "negdi2_compare"
+(define_insn "negdi2_compare"
   [(set (reg:CC CC_REGNUM)
 	(compare:CC
 	  (const_int 0)
-	  (match_operand:DI 1 "register_operand" "0,r")))
-   (set (match_operand:DI 0 "register_operand" "=r,&r")
+	  (match_operand:DI 1 "register_operand" "r,r")))
+   (set (match_operand:DI 0 "register_operand" "=&r,&r")
 	(minus:DI (const_int 0) (match_dup 1)))]
   "TARGET_ARM"
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (const_int 0) (match_dup 1)))
-	      (set (match_dup 0) (minus:SI (const_int 0)
-					   (match_dup 1)))])
-   (parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (const_int 0) (match_dup 3)))
-	     (set (match_dup 2)
-		  (minus:SI
-		   (minus:SI (const_int 0) (match_dup 3))
-		   (ltu:SI (reg:CC CC_REGNUM)
-			   (const_int 0))))])]
-  {
-    operands[2] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[3] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-  }
+  "@
+   rsbs\\t%Q0, %Q1, #0;rscs\\t%R0, %R1, #0
+   rsbs\\t%Q0, %Q1, #0;sbcs\\t%R0, %R1, %R1, lsl #1"
   [(set_attr "conds" "set")
+   (set_attr "arch" "a,t2")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
 )
@@ -4088,45 +3694,20 @@  (define_expand "negdi2"
 )
 
 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
-;; The first alternative allows the common case of a *full* overlap.
-(define_insn_and_split "*negdi2_insn"
-  [(set (match_operand:DI         0 "s_register_operand" "=r,&r")
-	(neg:DI (match_operand:DI 1 "s_register_operand"  "0,r")))
+(define_insn "*negdi2_insn"
+  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
+	(neg:DI (match_operand:DI 1 "s_register_operand"  "r,r")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_32BIT"
-  "#"	; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0	       (ARM)
-	; negs %Q0, %Q1    ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
-  "TARGET_32BIT"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (const_int 0) (match_dup 1)))
-	      (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
-   (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
-                                (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-    operands[2] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[3] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-  }
+  "@
+   rsbs\\t%Q0, %Q1, #0; rsc\\t%R0, %R1, #0
+   negs\\t%Q0, %Q1; sbc\\t%R0, %R1, %R1, lsl #1"
   [(set_attr "conds" "clob")
+   (set_attr "arch" "a,t2")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
 )
 
-(define_insn "*negsi2_carryin_compare"
-  [(set (reg:CC CC_REGNUM)
-	(compare:CC (const_int 0)
-		    (match_operand:SI 1 "s_register_operand" "r")))
-   (set (match_operand:SI 0 "s_register_operand" "=r")
-	(minus:SI (minus:SI (const_int 0)
-			    (match_dup 1))
-		  (match_operand:SI 2 "arm_borrow_operation" "")))]
-  "TARGET_ARM"
-  "rscs\\t%0, %1, #0"
-  [(set_attr "conds" "set")
-   (set_attr "type" "alus_imm")]
-)
-
 (define_expand "negsi2"
   [(set (match_operand:SI         0 "s_register_operand")
 	(neg:SI (match_operand:SI 1 "s_register_operand")))]
@@ -4249,29 +3830,6 @@  (define_insn_and_split "*negdi_extendsidi"
    (set_attr "type" "multiple")]
 )
 
-(define_insn_and_split "*negdi_zero_extendsidi"
-  [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
-	(neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
-      ;; Don't care what register is input to sbc,
-      ;; since we just need to propagate the carry.
-  "&& reload_completed"
-  [(parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (const_int 0) (match_dup 1)))
-	      (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
-   (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
-				(ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
-  {
-    operands[2] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-  }
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]   ;; length in thumb is 4
-)
-
 ;; abssi2 doesn't really clobber the condition codes if a different register
 ;; is being set.  To keep things simple, assume during rtl manipulations that
 ;; it does, but tell the final scan operator the truth.  Similarly for
@@ -6824,42 +6382,13 @@  (define_insn "*arm_cmpsi_negshiftsi_si"
 ;; if-conversion cannot reduce to a conditional compare, so we do
 ;; that directly.
 
-(define_insn_and_split "*arm_cmpdi_insn"
+(define_insn "*arm_cmpdi_insn"
   [(set (reg:CC_NCV CC_REGNUM)
 	(compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
 			(match_operand:DI 1 "arm_di_operand"	   "rDi")))
    (clobber (match_scratch:SI 2 "=r"))]
   "TARGET_32BIT"
-  "#"   ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
-  "&& reload_completed"
-  [(set (reg:CC CC_REGNUM)
-	(compare:CC (match_dup 0) (match_dup 1)))
-   (parallel [(set (reg:CC CC_REGNUM)
-		   (compare:CC (match_dup 3) (match_dup 4)))
-	      (set (match_dup 2)
-		   (minus:SI (match_dup 5)
-			     (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    if (CONST_INT_P (operands[1]))
-      {
-	operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);
-	if (operands[4] == const0_rtx)
-	  operands[5] = operands[3];
-	else
-	  operands[5] = gen_rtx_PLUS (SImode, operands[3],
-				      gen_int_mode (-UINTVAL (operands[4]),
-						    SImode));
-      }
-    else
-      {
-        operands[4] = gen_highpart (SImode, operands[1]);
-        operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
-      }
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }
+  "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
   [(set_attr "conds" "set")
    (set_attr "length" "8")
    (set_attr "type" "multiple")]
diff --git a/gcc/testsuite/gcc.target/arm/negdi-3.c b/gcc/testsuite/gcc.target/arm/negdi-3.c
index 76ddf49fc0d..3f6f2d1c2bb 100644
--- a/gcc/testsuite/gcc.target/arm/negdi-3.c
+++ b/gcc/testsuite/gcc.target/arm/negdi-3.c
@@ -11,7 +11,7 @@  Expected output:
         rsbs    r0, r0, #0
         sbc     r1, r1, r1
 */
-/* { dg-final { scan-assembler-times "rsb" 1 } } */
-/* { dg-final { scan-assembler-times "sbc" 1 } } */
-/* { dg-final { scan-assembler-times "mov" 0 } } */
-/* { dg-final { scan-assembler-times "rsc" 0 } } */
+/* { dg-final { scan-assembler-times "rsb" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "sbc" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "mov" 0 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "rsc" 0 { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr53447-1.c b/gcc/testsuite/gcc.target/arm/pr53447-1.c
index dc094180c85..0fd98b791fe 100644
--- a/gcc/testsuite/gcc.target/arm/pr53447-1.c
+++ b/gcc/testsuite/gcc.target/arm/pr53447-1.c
@@ -1,6 +1,6 @@ 
 /* { dg-options "-O2" }  */
 /* { dg-require-effective-target arm32 } */
-/* { dg-final { scan-assembler-not "mov" } } */
+/* { dg-final { scan-assembler-not "mov" { xfail *-*-* } } } */
 
 void t0p(long long * p)
 {
diff --git a/gcc/testsuite/gcc.target/arm/pr53447-3.c b/gcc/testsuite/gcc.target/arm/pr53447-3.c
index 8e48f119b74..79d3691ee14 100644
--- a/gcc/testsuite/gcc.target/arm/pr53447-3.c
+++ b/gcc/testsuite/gcc.target/arm/pr53447-3.c
@@ -1,6 +1,6 @@ 
 /* { dg-options "-O2" }  */
 /* { dg-require-effective-target arm32 } */
-/* { dg-final { scan-assembler-not "mov" } } */
+/* { dg-final { scan-assembler-not "mov" { xfail *-*-* } } } */
 
 
 void t0p(long long * p)
diff --git a/gcc/testsuite/gcc.target/arm/pr53447-4.c b/gcc/testsuite/gcc.target/arm/pr53447-4.c
index 22acb97270e..bfa20df7ccd 100644
--- a/gcc/testsuite/gcc.target/arm/pr53447-4.c
+++ b/gcc/testsuite/gcc.target/arm/pr53447-4.c
@@ -1,6 +1,6 @@ 
 /* { dg-options "-O2" }  */
 /* { dg-require-effective-target arm32 } */
-/* { dg-final { scan-assembler-not "mov" } } */
+/* { dg-final { scan-assembler-not "mov" { xfail *-*-* } } } */
 
 
 void t0p(long long * p)