diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8afa6d11b11ee6f2a20cd12670b57a8c057861ce..1367409ac37fb2eefff11d3300c3fdf1e9861d92 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2009-11-04  Richard Earnshaw  <rearnsha@arm.com>
+
+	PR target/40835
+	* arm.md (peephole2 patterns for move and compare): New.
+
 2009-11-04  Nick Clifton  <nickc@redhat.com>
 
 	* defaults.h (CONSTANT_ADDRESS_P): Provide a default definition.
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index b8bf700242b228524e481527f2c4ca7042949c06..fbc52f4600f8ad89969dc4cf91f88b4efa49dfcf 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -6770,6 +6770,7 @@
 		(const_int 6)
 		(const_int 8))))]
 )
+
 (define_insn "*movsi_cbranchsi4"
   [(set (pc)
 	(if_then_else
@@ -6833,6 +6834,45 @@
 	   (const_int 10)))))]
 )
 
+(define_peephole2
+  [(set (match_operand:SI 0 "low_register_operand" "")
+	(match_operand:SI 1 "low_register_operand" ""))
+   (set (pc)
+	(if_then_else (match_operator 2 "arm_comparison_operator"
+		       [(match_dup 1) (const_int 0)])
+		      (label_ref (match_operand 3 "" ""))
+		      (pc)))]
+  "TARGET_THUMB1"
+  [(parallel
+    [(set (pc)
+	(if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
+		      (label_ref (match_dup 3))
+		      (pc)))
+     (set (match_dup 0) (match_dup 1))])]
+  ""
+)
+
+;; Sigh!  This variant shouldn't be needed, but combine often fails to
+;; merge cases like this because the op1 is a hard register in
+;; CLASS_LIKELY_SPILLED_P.
+(define_peephole2
+  [(set (match_operand:SI 0 "low_register_operand" "")
+	(match_operand:SI 1 "low_register_operand" ""))
+   (set (pc)
+	(if_then_else (match_operator 2 "arm_comparison_operator"
+		       [(match_dup 0) (const_int 0)])
+		      (label_ref (match_operand 3 "" ""))
+		      (pc)))]
+  "TARGET_THUMB1"
+  [(parallel
+    [(set (pc)
+	(if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
+		      (label_ref (match_dup 3))
+		      (pc)))
+     (set (match_dup 0) (match_dup 1))])]
+  ""
+)
+
 (define_insn "*negated_cbranchsi4"
   [(set (pc)
 	(if_then_else
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5ef448ced8ac678f4ca98dfa173dae3332a8dcb5..62d1625485bfbbc53dd55fee78d9c4f41ac87ca7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-11-04  Wei Guozhi  <carrot@google.com>
+
+	PR target/40835
+	* gcc.target/arm/pr40835: New testcase.
+
 2009-11-04  Revital Eres  <eres@il.ibm.com>
 
 	* gcc.target/powerpc/vsx-vectorize-3.c: Adjust tetcase following
diff --git a/gcc/testsuite/gcc.target/arm/pr40835.c b/gcc/testsuite/gcc.target/arm/pr40835.c
new file mode 100644
index 0000000000000000000000000000000000000000..baf940321017b0ff3c4d1d231003a7f8165e456a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr40835.c
@@ -0,0 +1,55 @@
+/* { dg-options "-mthumb -Os -march=armv5te" }  */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+int bar();
+void goo(int, int);
+
+void eq()
+{
+  int v = bar();
+  if (v == 0)
+    return;
+  goo(1, v);
+}
+
+void ge()
+{
+  int v = bar();
+  if (v >= 0)
+    return;
+  goo(1, v);
+}
+
+void gt()
+{
+  int v = bar();
+  if (v > 0)
+    return;
+  goo(1, v);
+}
+
+void lt()
+{
+  int v = bar();
+  if (v < 0)
+    return;
+  goo(1, v);
+}
+
+void le()
+{
+  int v = bar();
+  if (v <= 0)
+    return;
+  goo(1, v);
+}
+
+unsigned int foo();
+
+void leu()
+{
+  unsigned int v = foo();
+  if (v <= 0)
+    return;
+  goo(1, v);
+}