diff mbox series

[5/5,Arm] New pattern for CSEL, CSET and CSETM instructions

Message ID AM0PR08MB5121BE4F7AF116F419CD4C37924A0@AM0PR08MB5121.eurprd08.prod.outlook.com
State New
Headers show
Series Add support for conditional instructions (CSEL, CSINC etc.) for Armv8.1-M Mainline | expand

Commit Message

Omar Tahir Aug. 4, 2020, 4:16 p.m. UTC
This patch adds a new pattern, *cmovsi_insn, for generating CSEL, CSET and
CSETM instructions. It also generates CSINV and CSINC instructions in specific
cases where one of the operands is constant.

To facilitate this, one new predicate and two new constraints are added, and
*compare_scc is restricted to only match if !TARGET_COND_ARITH to prevent
an unwanted split. Additionally, alternatives 8-10 are re-enabled in
*thumnb2_movsicc_insn and splitting only occurs if !TARGET_COND_ARITH. This
forces the new pattern to be used when possible, but for more complex cases
that can't directly use CSEL it falls back to using IT blocks.

Regression tested on arm-none-eabi. The entire patch set was regression
tested on arm-linux-gnueabi also.

That's all folks!

Thanks,
Omar


2020-07-30: Sudakshina Das <sudi.das@arm.com>
            Omar Tahir <omar.tahir@arm.com>

                * config/arm/thumb2.md (*cmovsi_insn): New.
                (*thumb2_movsicc_insn): Don't split if TARGET_COND_ARITH, re-enable
                alternatives 8-10.
                * config/arm/arm.md (*compare_scc): Don't match if TARGET_COND_ARITH.


gcc/testsuite/ChangeLog:

2020-07-30: Omar Tahir <omar.tahir@arm.com>

                * gcc.target/arm/csel.c: New test.
                * gcc.target/arm/cset.c: New test.
                * gcc.target/arm/csetm.c: New test.
                * gcc.target/arm/csinv-2.c: New test.
                * gcc.target/arm/csinc-2.c: New test.

Comments

Kyrylo Tkachov Aug. 7, 2020, 8:15 a.m. UTC | #1
Hi Omar,

From: Omar Tahir <Omar.Tahir@arm.com> 
Sent: 04 August 2020 17:16
To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>; nickc@redhat.com; Ramana Radhakrishnan <Ramana.Radhakrishnan@arm.com>; Richard Earnshaw <Richard.Earnshaw@arm.com>; gcc-patches@gcc.gnu.org
Subject: [PATCH 5/5][Arm] New pattern for CSEL, CSET and CSETM instructions

This patch adds a new pattern, *cmovsi_insn, for generating CSEL, CSET and
CSETM instructions. It also generates CSINV and CSINC instructions in specific
cases where one of the operands is constant.

To facilitate this, one new predicate and two new constraints are added, and
*compare_scc is restricted to only match if !TARGET_COND_ARITH to prevent
an unwanted split. Additionally, alternatives 8-10 are re-enabled in
*thumnb2_movsicc_insn and splitting only occurs if !TARGET_COND_ARITH. This
forces the new pattern to be used when possible, but for more complex cases
that can't directly use CSEL it falls back to using IT blocks.

Regression tested on arm-none-eabi. The entire patch set was regression
tested on arm-linux-gnueabi also.

That's all folks!

Thanks,
Omar


2020-07-30: Sudakshina Das <mailto:sudi.das@arm.com>
            Omar Tahir <mailto:omar.tahir@arm.com>

	* config/arm/thumb2.md (*cmovsi_insn): New.
	(*thumb2_movsicc_insn): Don't split if TARGET_COND_ARITH, re-enable
	alternatives 8-10.
	* config/arm/arm.md (*compare_scc): Don't match if TARGET_COND_ARITH.
	

gcc/testsuite/ChangeLog:

2020-07-30: Omar Tahir <mailto:omar.tahir@arm.com>

	* gcc.target/arm/csel.c: New test.
	* gcc.target/arm/cset.c: New test.
	* gcc.target/arm/csetm.c: New test.
	* gcc.target/arm/csinv-2.c: New test.
	* gcc.target/arm/csinc-2.c: New test.


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"

Hmm... I think the approach makes sense, but I'd rather we left the alternatives as '#'  and refine the condition so that in the TARGET_COND_ARITH case we split in precisely the cases where the TARGET_COND_ARITH can't handle the operands.
I appreciate that would complicate this condition somewhat, but it would have the benefit of expressing the RTL structure to allow for further optimisation.

Thanks,
Kyrill 


   [(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;
+}
diff mbox series

Patch

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;
+}