diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 950e46edfee..b8dd6af50a8 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -9760,7 +9760,7 @@
 	 [(match_operand:SI 2 "s_register_operand" "r,r")
 	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
+  "TARGET_32BIT && !TARGET_COND_ARITH"
   "#"
   "&& reload_completed"
   [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index 048b25ef4a1..37d240d139b 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -37,7 +37,7 @@
 ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe
 ;; in Thumb-2 state: Ha, Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py, Pz, Rd, Rf, Rb, Ra,
 ;;		     Rg, Ri
-;; in all states: Pf, Pg
+;; in all states: Pf, Pg, UM, U1
 
 ;; The following memory constraints have been used:
 ;; in ARM/Thumb-2 state: Uh, Ut, Uv, Uy, Un, Um, Us, Up, Uf, Ux, Ul
@@ -485,6 +485,16 @@
    Integer constant zero."
   (match_test "op == const0_rtx"))
 
+(define_constraint "UM"
+  "@internal
+   A constraint that matches the immediate constant -1."
+  (match_test "op == constm1_rtx"))
+
+(define_constraint "U1"
+  "@internal
+   A constraint that matches the immediate constant +1."
+  (match_test "op == const1_rtx"))
+
 (define_memory_constraint "Ux"
  "@internal
   In ARM/Thumb-2 state a valid address and load into CORE regs or only to
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 2144520829c..5d75341c9ef 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -454,6 +454,13 @@
 		    && arm_general_register_operand (op, GET_MODE (op))")
        (match_test "satisfies_constraint_Pg (op)")))
 
+(define_predicate "arm_reg_or_m1_or_1_or_zero"
+  (and (match_code "reg,subreg,const_int")
+       (ior (match_operand 0 "arm_general_register_operand")
+            (match_test "op == constm1_rtx")
+            (match_test "op == const1_rtx")
+            (match_test "op == const0_rtx"))))
+
 ;; True for MULT, to identify which variant of shift_operator is in use.
 (define_special_predicate "mult_operator"
   (match_code "mult"))
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index d12467d7644..bc6f2a52004 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -432,6 +432,30 @@
    (set_attr "type" "multiple")]
 )
 
+(define_insn "*cmovsi_insn"
+  [(set (match_operand:SI 0 "arm_general_register_operand" "=r,r,r,r,r,r,r,r,r")
+        (if_then_else:SI
+         (match_operator 1 "arm_comparison_operator"
+          [(match_operand 2 "cc_register" "") (const_int 0)])
+         (match_operand:SI 3 "arm_reg_or_m1_or_1_or_zero" "r, r,UM, r,U1,U1, Z,UM, Z")
+         (match_operand:SI 4 "arm_reg_or_m1_or_1_or_zero" "r,UM, r,U1, r, Z,U1, Z,UM")))]
+  "TARGET_THUMB2 && TARGET_COND_ARITH
+   && (!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
+       || (operands[3] == constm1_rtx && operands[4] == const1_rtx)))"
+  "@
+   csel\\t%0, %3, %4, %d1
+   csinv\\t%0, %3, zr, %d1
+   csinv\\t%0, %4, zr, %D1
+   csinc\\t%0, %3, zr, %d1
+   csinc\\t%0, %4, zr, %D1
+   cset\\t%0, %d1
+   cset\\t%0, %D1
+   csetm\\t%0, %d1
+   csetm\\t%0, %D1"
+  [(set_attr "type" "csel")
+   (set_attr "predicable" "no")]
+)
+
 (define_insn_and_split "*thumb2_movsicc_insn"
   [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r")
 	(if_then_else:SI
@@ -449,17 +473,14 @@
    it\\t%d3\;mvn%d3\\t%0, #%B1
    #
    #
-   #
-   #
-   #
+   ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
+   ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
+   ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
    #"
    ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
    ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
-   ; alt 8: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
-   ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
-   ; alt 10: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
    ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
-  "&& reload_completed"
+  "&& reload_completed && !TARGET_COND_ARITH"
   [(const_int 0)]
   {
     enum rtx_code rev_code;
diff --git a/gcc/testsuite/gcc.target/arm/csel.c b/gcc/testsuite/gcc.target/arm/csel.c
new file mode 100644
index 00000000000..79a4c161eb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/csel.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8_1m_main_ok } */
+/* { dg-options "-O2 -march=armv8.1-m.main" } */
+
+int
+test_csel32_condasn(int w0, int w1, int w2, int w3)
+{
+  int w4;
+
+  /* { dg-final { scan-assembler "csel\tr\[0-9\]*.*eq" } } */
+  w4 = (w0 == w1) ? w2 : w3;
+  return w4;
+}
diff --git a/gcc/testsuite/gcc.target/arm/cset.c b/gcc/testsuite/gcc.target/arm/cset.c
new file mode 100644
index 00000000000..e63b7b5041e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/cset.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8_1m_main_ok } */
+/* { dg-options "-O2 -march=armv8.1-m.main" } */
+
+int
+test_cset32_condasn1(int w0, int w1)
+{
+  int w2;
+
+  /* { dg-final { scan-assembler "cset\tr\[0-9\]*.*eq" } } */
+  w2 = (w0 == w1) ? 1 : 0;
+  return w2;
+}
+
+int
+test_cset32_condasn2(int w0, int w1)
+{
+  int w2;
+
+  /* { dg-final { scan-assembler "cset\tr\[0-9\]*.*ne" } } */
+  w2 = (w0 == w1) ? 0 : 1;
+  return w2;
+}
diff --git a/gcc/testsuite/gcc.target/arm/csetm.c b/gcc/testsuite/gcc.target/arm/csetm.c
new file mode 100644
index 00000000000..c04520c2f65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/csetm.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8_1m_main_ok } */
+/* { dg-options "-O2 -march=armv8.1-m.main" } */
+
+int
+test_csetm32_condasn1(int w0, int w1)
+{
+  int w2;
+
+  /* { dg-final { scan-assembler "csetm\tr\[0-9\]*.*eq" } } */
+  w2 = (w0 == w1) ? -1 : 0;
+  return w2;
+}
+
+int
+test_csetm32_condasn2(int w0, int w1)
+{
+  int w2;
+
+  /* { dg-final { scan-assembler "csetm\tr\[0-9\]*.*ne" } } */
+  w2 = (w0 == w1) ? 0 : -1;
+  return w2;
+}
diff --git a/gcc/testsuite/gcc.target/arm/csinc-2.c b/gcc/testsuite/gcc.target/arm/csinc-2.c
new file mode 100644
index 00000000000..45e3815eb0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/csinc-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8_1m_main_ok } */
+/* { dg-options "-O2 -march=armv8.1-m.main" } */
+
+int
+test_csinc32_condasn1(int w0, int w1, int w2)
+{
+  int w3;
+
+  /* { dg-final { scan-assembler "csinc\tr\[0-9\]*.*zr.*eq" } } */
+  w3 = (w0 == w1) ? w2 : 1;
+  return w3;
+}
+
+int
+test_csinc32_condasn2(int w0, int w1, int w2)
+{
+  int w3;
+
+  /* { dg-final { scan-assembler "csinc\tr\[0-9\]*.*zr.*ne" } } */
+  w3 = (w0 == w1) ? 1 : w2;
+  return w3;
+}
diff --git a/gcc/testsuite/gcc.target/arm/csinv-2.c b/gcc/testsuite/gcc.target/arm/csinv-2.c
new file mode 100644
index 00000000000..d55de1b5a33
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/csinv-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8_1m_main_ok } */
+/* { dg-options "-O2 -march=armv8.1-m.main" } */
+
+int
+test_csinv32_condasn1(int w0, int w1, int w2)
+{
+  int w3;
+
+  /* { dg-final { scan-assembler "csinv\tr\[0-9\]*.*zr.*eq" } } */
+  w3 = (w0 == w1) ? w2 : -1;
+  return w3;
+}
+
+int
+test_csinv32_condasn2(int w0, int w1, int w2)
+{
+  int w3;
+
+  /* { dg-final { scan-assembler "csinv\tr\[0-9\]*.*zr.*ne" } } */
+  w3 = (w0 == w1) ? -1 : w2;
+  return w3;
+}
