Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 189835)
+++ gcc/config/arm/arm.c	(working copy)
@@ -21663,6 +21663,8 @@
       if (cfun->machine->thumb1_cc_insn)
 	{
 	  if (modified_in_p (cfun->machine->thumb1_cc_op0, insn)
+	      || (cfun->machine->thumb1_cc_op0_src != NULL_RTX
+		  && modified_in_p (cfun->machine->thumb1_cc_op0_src, insn))
 	      || modified_in_p (cfun->machine->thumb1_cc_op1, insn))
 	    CC_STATUS_INIT;
 	}
@@ -21672,13 +21674,18 @@
 	  rtx set = single_set (insn);
 	  cfun->machine->thumb1_cc_insn = insn;
 	  cfun->machine->thumb1_cc_op0 = SET_DEST (set);
+	  cfun->machine->thumb1_cc_op0_src = NULL_RTX;
 	  cfun->machine->thumb1_cc_op1 = const0_rtx;
 	  cfun->machine->thumb1_cc_mode = CC_NOOVmode;
 	  if (INSN_CODE (insn) == CODE_FOR_thumb1_subsi3_insn)
 	    {
 	      rtx src1 = XEXP (SET_SRC (set), 1);
 	      if (src1 == const0_rtx)
-		cfun->machine->thumb1_cc_mode = CCmode;
+		{
+		  cfun->machine->thumb1_cc_mode = CCmode;
+		  /* Record the minuend in thumb1_subsi3_insn pattern.  */
+		  cfun->machine->thumb1_cc_op0_src = XEXP (SET_SRC (set), 0);
+		}
 	    }
 	}
       else if (conds != CONDS_NOCOND)
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	(revision 189835)
+++ gcc/config/arm/arm.h	(working copy)
@@ -1459,9 +1459,17 @@
      is not needed.  */
   int return_used_this_function;
   /* When outputting Thumb-1 code, record the last insn that provides
-     information about condition codes, and the comparison operands.  */
+     information about condition codes, and the comparison operands.
+
+     If the last insn that provides information about condition codes
+     is in the form of "dest_reg = src_reg - 0", record the src_reg in
+     thumb1_cc_op0_src, and for following insn sequence:
+	 dest_reg = src_reg - 0;
+	 if (src_reg ?= 0) goto label;
+     the comparison insn can also be saved.  */
   rtx thumb1_cc_insn;
   rtx thumb1_cc_op0;
+  rtx thumb1_cc_op0_src;
   rtx thumb1_cc_op1;
   /* Also record the CC mode that is supported.  */
   enum machine_mode thumb1_cc_mode;
Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md	(revision 189835)
+++ gcc/config/arm/arm.md	(working copy)
@@ -7018,7 +7018,8 @@
   rtx t = cfun->machine->thumb1_cc_insn;
   if (t != NULL_RTX)
     {
-      if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
+      if ((!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
+	   && !rtx_equal_p (cfun->machine->thumb1_cc_op0_src, operands[1]))
 	  || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
 	t = NULL_RTX;
       if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
@@ -7034,6 +7035,7 @@
       output_asm_insn ("cmp\t%1, %2", operands);
       cfun->machine->thumb1_cc_insn = insn;
       cfun->machine->thumb1_cc_op0 = operands[1];
+      cfun->machine->thumb1_cc_op0_src = NULL_RTX;
       cfun->machine->thumb1_cc_op1 = operands[2];
       cfun->machine->thumb1_cc_mode = CCmode;
     }
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c	(revision 189835)
+++ gcc/regcprop.c	(working copy)
@@ -1019,8 +1019,18 @@
       note_stores (PATTERN (insn), kill_set_value, &ksvd);
 
       /* Notice copies.  */
-      if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))
-	copy_value (SET_DEST (set), SET_SRC (set), vd);
+      if (set && REG_P (SET_DEST (set)))
+	{
+	  if (REG_P (SET_SRC (set)))
+	    copy_value (SET_DEST (set), SET_SRC (set), vd);
+	  /* ARM backend intentionally rewrite move insn into subtract of 0 if
+	     the condition codes will be useful, so also notice this case.  */
+	  else if ((GET_CODE (SET_SRC (set)) == PLUS
+		    || GET_CODE (SET_SRC (set)) == MINUS)
+		   && REG_P (XEXP (SET_SRC (set), 0))
+		   && XEXP (SET_SRC (set), 1) == const0_rtx)
+	    copy_value (SET_DEST (set), XEXP (SET_SRC (set), 0), vd);
+	}
 
       if (insn == BB_END (bb))
 	break;
