diff options
author | Dimitar Dimitrov <dimitar@dinux.eu> | 2023-06-13 22:20:13 +0300 |
---|---|---|
committer | Dimitar Dimitrov <dimitar@dinux.eu> | 2023-08-30 21:55:56 +0300 |
commit | ee077d0c5793e1d4ad8d3b033ef2f0225ba6bd59 (patch) | |
tree | c6077ce342b2ccdf0af936eec01902cb0c47b5c2 | |
parent | 4a92205ef1da044eaf9490e61787836a3abe7d6c (diff) | |
download | gcc-ee077d0c5793e1d4ad8d3b033ef2f0225ba6bd59.zip gcc-ee077d0c5793e1d4ad8d3b033ef2f0225ba6bd59.tar.gz gcc-ee077d0c5793e1d4ad8d3b033ef2f0225ba6bd59.tar.bz2 |
pru: Add cstore expansion patterns
Add cstore patterns for the two specific operations which can be
efficiently expanded using the UMIN instruction:
X != 0
X == 0
The rest of the operations are rejected, and left to be expanded
by the common expansion code.
PR target/106562
gcc/ChangeLog:
* config/pru/predicates.md (const_0_operand): New predicate.
(pru_cstore_comparison_operator): Ditto.
* config/pru/pru.md (cstore<mode>4): New pattern.
(cstoredi4): Ditto.
gcc/testsuite/ChangeLog:
* gcc.target/pru/pr106562-10.c: New test.
* gcc.target/pru/pr106562-11.c: New test.
* gcc.target/pru/pr106562-5.c: New test.
* gcc.target/pru/pr106562-6.c: New test.
* gcc.target/pru/pr106562-7.c: New test.
* gcc.target/pru/pr106562-8.c: New test.
* gcc.target/pru/pr106562-9.c: New test.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
-rw-r--r-- | gcc/config/pru/predicates.md | 8 | ||||
-rw-r--r-- | gcc/config/pru/pru.md | 62 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/pru/pr106562-10.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/pru/pr106562-11.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/pru/pr106562-5.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/pru/pr106562-6.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/pru/pr106562-7.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/pru/pr106562-8.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/pru/pr106562-9.c | 8 |
9 files changed, 126 insertions, 0 deletions
diff --git a/gcc/config/pru/predicates.md b/gcc/config/pru/predicates.md index e4a7fcf..faa0dbf 100644 --- a/gcc/config/pru/predicates.md +++ b/gcc/config/pru/predicates.md @@ -22,6 +22,10 @@ (and (match_code "const_int") (match_test "INTVAL (op) == 1"))) +(define_predicate "const_0_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) == 0"))) + ; Note: Always pass a valid mode! (define_predicate "const_ubyte_operand" (match_code "const_int") @@ -49,6 +53,10 @@ (define_predicate "pru_fp_comparison_operator" (match_code "eq,ne,lt,gt,le,ge")) +;; TRUE for comparisons supported by PRU's cstore. +(define_predicate "pru_cstore_comparison_operator" + (match_code "eq,ne,gtu")) + ;; Return true if OP is a constant that contains only one 1 in its ;; binary representation. (define_predicate "single_one_operand" diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md index 6deb5ec..93ad7b6 100644 --- a/gcc/config/pru/pru.md +++ b/gcc/config/pru/pru.md @@ -1489,6 +1489,68 @@ gcc_unreachable (); }) +;; Emit efficient code for two specific cstore cases: +;; X == 0 +;; X != 0 +;; +;; These can be efficiently compiled on the PRU using the umin +;; instruction. +;; +;; This expansion does not handle "X > 0 unsigned" and "X >= 1 unsigned" +;; because it is assumed that those would have been replaced with the +;; canonical "X != 0". +(define_expand "cstore<mode>4" + [(set (match_operand:QISI 0 "register_operand") + (match_operator:QISI 1 "pru_cstore_comparison_operator" + [(match_operand:QISI 2 "register_operand") + (match_operand:QISI 3 "const_0_operand")]))] + "" +{ + const enum rtx_code op1code = GET_CODE (operands[1]); + + /* Crash if OP1 is GTU. It would mean that "X > 0 unsigned" + had not been canonicalized before calling this expansion. */ + gcc_assert (op1code == NE || op1code == EQ); + gcc_assert (CONST_INT_P (operands[3]) && INTVAL (operands[3]) == 0); + + if (op1code == NE) + { + emit_insn (gen_umin<mode>3 (operands[0], operands[2], const1_rtx)); + DONE; + } + else if (op1code == EQ) + { + rtx tmpval = gen_reg_rtx (<MODE>mode); + emit_insn (gen_umin<mode>3 (tmpval, operands[2], const1_rtx)); + emit_insn (gen_xor<mode>3 (operands[0], tmpval, const1_rtx)); + DONE; + } + + gcc_unreachable (); +}) + +(define_expand "cstoredi4" + [(set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "pru_cstore_comparison_operator" + [(match_operand:DI 2 "register_operand") + (match_operand:DI 3 "const_0_operand")]))] + "" +{ + /* Combining the two SImode suboperands with IOR works only for + the currently supported set of cstoresi3 operations. */ + const enum rtx_code op1code = GET_CODE (operands[1]); + gcc_assert (op1code == NE || op1code == EQ); + gcc_assert (CONST_INT_P (operands[3]) && INTVAL (operands[3]) == 0); + + rtx tmpval = gen_reg_rtx (SImode); + rtx src_lo = simplify_gen_subreg (SImode, operands[2], DImode, 0); + rtx src_hi = simplify_gen_subreg (SImode, operands[2], DImode, 4); + emit_insn (gen_iorsi3 (tmpval, src_lo, src_hi)); + emit_insn (gen_cstoresi4 (operands[0], operands[1], tmpval, const0_rtx)); + + DONE; +}) + ; ; Bit test branch diff --git a/gcc/testsuite/gcc.target/pru/pr106562-10.c b/gcc/testsuite/gcc.target/pru/pr106562-10.c new file mode 100644 index 0000000..7f0224c --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr106562-10.c @@ -0,0 +1,8 @@ +/* { dg-do assemble } */ +/* { dg-options "-Os" } */ +/* { dg-final { object-size text <= 16 } } */ + +int test(long long a) +{ + return a == 0; +} diff --git a/gcc/testsuite/gcc.target/pru/pr106562-11.c b/gcc/testsuite/gcc.target/pru/pr106562-11.c new file mode 100644 index 0000000..017aa49 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr106562-11.c @@ -0,0 +1,8 @@ +/* { dg-do assemble } */ +/* { dg-options "-Os" } */ +/* { dg-final { object-size text <= 12 } } */ + +int test(unsigned long long a) +{ + return a > 0; +} diff --git a/gcc/testsuite/gcc.target/pru/pr106562-5.c b/gcc/testsuite/gcc.target/pru/pr106562-5.c new file mode 100644 index 0000000..16d9dfa --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr106562-5.c @@ -0,0 +1,8 @@ +/* { dg-do assemble } */ +/* { dg-options "-Os" } */ +/* { dg-final { object-size text <= 8 } } */ + +int test(int a) +{ + return a != 0; +} diff --git a/gcc/testsuite/gcc.target/pru/pr106562-6.c b/gcc/testsuite/gcc.target/pru/pr106562-6.c new file mode 100644 index 0000000..59510d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr106562-6.c @@ -0,0 +1,8 @@ +/* { dg-do assemble } */ +/* { dg-options "-Os" } */ +/* { dg-final { object-size text <= 8 } } */ + +int test(unsigned a) +{ + return a > 0; +} diff --git a/gcc/testsuite/gcc.target/pru/pr106562-7.c b/gcc/testsuite/gcc.target/pru/pr106562-7.c new file mode 100644 index 0000000..ca833ef --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr106562-7.c @@ -0,0 +1,8 @@ +/* { dg-do assemble } */ +/* { dg-options "-Os" } */ +/* { dg-final { object-size text <= 8 } } */ + +int test(unsigned a) +{ + return a >= 1; +} diff --git a/gcc/testsuite/gcc.target/pru/pr106562-8.c b/gcc/testsuite/gcc.target/pru/pr106562-8.c new file mode 100644 index 0000000..2911d84 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr106562-8.c @@ -0,0 +1,8 @@ +/* { dg-do assemble } */ +/* { dg-options "-Os" } */ +/* { dg-final { object-size text <= 12 } } */ + +int test(int a) +{ + return a == 0; +} diff --git a/gcc/testsuite/gcc.target/pru/pr106562-9.c b/gcc/testsuite/gcc.target/pru/pr106562-9.c new file mode 100644 index 0000000..25ece1c --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr106562-9.c @@ -0,0 +1,8 @@ +/* { dg-do assemble } */ +/* { dg-options "-Os" } */ +/* { dg-final { object-size text <= 12 } } */ + +int test(long long a) +{ + return a != 0; +} |