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

Omar Tahir Omar.Tahir@arm.com
Tue Aug 4 16:16:13 GMT 2020


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.


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;
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: csel_5.patch
Type: application/octet-stream
Size: 7599 bytes
Desc: csel_5.patch
URL: <https://gcc.gnu.org/pipermail/gcc-patches/attachments/20200804/aae8c7f1/attachment-0001.obj>


More information about the Gcc-patches mailing list