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....@arm.com> Omar Tahir <omar.ta...@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.ta...@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; +}
csel_5.patch
Description: csel_5.patch