Hi Kyrill,

> It's been a while, but I believe you had the following comment about 
> implementing CSEL:
>
>> (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.
>
> I've made the changes you suggested, let me know if it's good to commit.
>
>  (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
> @@ -459,7 +483,9 @@
>     ; 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"
> +   ; Conditional arithmetic (csel etc.) can handle all alternatives except 
> 8-10
> +  "&& reload_completed && (!TARGET_COND_ARITH ||
> +                           (which_alternative >= 8 && which_alternative <= 
> 10))"
>    [(const_int 0)]
>    {
>      enum rtx_code rev_code;

Here's an alternative implementation that doesn't use which_alternative.

Thanks,
Omar

--

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
950e46edfeeee1b851b8968cbcf071564416dbf6..b8dd6af50a842c924996d528e95ce9873dcb913a
 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 
011badc9957655a0fba67946c1db6fa6334b2bbb..57db29f92f4caee4c9384a9740e79dba2217144a
 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -36,7 +36,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
@@ -479,6 +479,16 @@
  (and (match_code "mem")
       (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 1, true)")))
+(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 
2144520829cc4a28cd7ac1ef528ecd54f0af13c1..5d75341c9efe82dcda27daa74d2b22c52065dd02
 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 
69460f3665b0bc7f47c307aa4ae789bab6a94f92..f15f99903dad36e53d9af664c5b3a5e1ebe3b78b
 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,Pz,UM,Pz")
+         (match_operand:SI 4 "arm_reg_or_m1_or_1_or_zero" "r,UM, r,U1, 
r,Pz,U1,Pz,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
@@ -459,7 +483,14 @@
    ; 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"
+   ; Conditional arithmetic (csel etc.) can handle all alternatives except 8-10
+  "&& reload_completed && (!TARGET_COND_ARITH ||
+                           (satisfies_constraint_K (operands[1]) &&
+                            !satisfies_constraint_I (operands[1]) &&
+                            operands[2] != const0_rtx) ||
+                           (satisfies_constraint_K (operands[2]) &&
+                            !satisfies_constraint_I (operands[2]) &&
+                            operands[1] != const0_rtx))"
   [(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 
0000000000000000000000000000000000000000..79a4c161eb52b2986c2c2990d2dda3d8c3628782
--- /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 
0000000000000000000000000000000000000000..e63b7b5041ece7905306876c2c6f9f2f95964951
--- /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 
0000000000000000000000000000000000000000..c04520c2f6514850b299208a477893ee40a02aca
--- /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 
0000000000000000000000000000000000000000..45e3815eb0c4f2d252e7f0326728dbd0f7debd86
--- /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 
0000000000000000000000000000000000000000..d55de1b5a3342128cfcb25f48361541d0ae38c06
--- /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;
+}

Attachment: rb13325(1).patch
Description: rb13325(1).patch

Reply via email to