From: Dimitar Dimitrov <dimitar@dinux.eu>
To: gcc-patches@gcc.gnu.org
Cc: Dimitar Dimitrov <dimitar@dinux.eu>
Subject: [COMMITTED 3/9] pru: Optimize the extzv and insv patterns
Date: Tue, 7 May 2024 10:22:35 +0300 [thread overview]
Message-ID: <974fb8bda715b7fc8b2f3f9e227bf9b516a22a53.1715065537.git.dimitar@dinux.eu> (raw)
In-Reply-To: <cover.1715065537.git.dimitar@dinux.eu>
Optimize the generated code for the bit-field extract and insert
patterns:
- Use bit-set and bit-clear instructions for 1-bit fields.
- Expand to SImode operations instead of relying on the default
expansion to word (QI) mode.
gcc/ChangeLog:
* config/pru/pru.md (extzv<mode>): Make it an expand pattern,
handle efficiently zero-positioned bit-fields.
(insv<mode>): New expand pattern.
gcc/testsuite/ChangeLog:
* gcc.target/pru/ashiftrt.c: Minor update due to new (but
equivalent) generated code sequence.
* gcc.target/pru/extzv-1.c: New test.
* gcc.target/pru/extzv-2.c: New test.
* gcc.target/pru/extzv-3.c: New test.
* gcc.target/pru/insv-1.c: New test.
* gcc.target/pru/insv-2.c: New test.
* gcc.target/pru/insv-3.c: New test.
* gcc.target/pru/insv-4.c: New test.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru.md | 104 ++++++++++++++++++++++--
gcc/testsuite/gcc.target/pru/ashiftrt.c | 2 +-
gcc/testsuite/gcc.target/pru/extzv-1.c | 14 ++++
gcc/testsuite/gcc.target/pru/extzv-2.c | 15 ++++
gcc/testsuite/gcc.target/pru/extzv-3.c | 13 +++
gcc/testsuite/gcc.target/pru/insv-1.c | 14 ++++
gcc/testsuite/gcc.target/pru/insv-2.c | 14 ++++
gcc/testsuite/gcc.target/pru/insv-3.c | 14 ++++
gcc/testsuite/gcc.target/pru/insv-4.c | 14 ++++
9 files changed, 194 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-3.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-3.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-4.c
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 0123952aa9e..2ceea2e7b1c 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -486,22 +486,108 @@ (define_expand "extend<EQS0:mode><EQDHIDI:mode>2"
})
\f
;; Bit extraction
-;; We define it solely to allow combine to choose SImode
+;; One reason to define it is to allow combine to choose SImode
;; for word mode when trying to match our cbranch_qbbx_* insn.
;;
;; Check how combine.cc:make_extraction() uses
;; get_best_reg_extraction_insn() to select the op size.
-(define_insn "extzv<mode>"
- [(set (match_operand:QISI 0 "register_operand" "=r")
+(define_expand "extzv<mode>"
+ [(set (match_operand:QISI 0 "register_operand")
(zero_extract:QISI
- (match_operand:QISI 1 "register_operand" "r")
- (match_operand:QISI 2 "const_int_operand" "i")
- (match_operand:QISI 3 "const_int_operand" "i")))]
+ (match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "const_int_operand")
+ (match_operand:QISI 3 "const_int_operand")))]
""
- "lsl\\t%0, %1, (%S0 * 8 - %2 - %3)\;lsr\\t%0, %0, (%S0 * 8 - %2)"
- [(set_attr "type" "complex")
- (set_attr "length" "8")])
+{
+ const int nbits = INTVAL (operands[2]);
+ const int bitpos = INTVAL (operands[3]);
+ const int trailing_bits = GET_MODE_BITSIZE (<MODE>mode) - nbits - bitpos;
+
+ if (bitpos == 0 && nbits <= 7)
+ {
+ emit_insn (gen_and<mode>3 (operands[0],
+ operands[1],
+ gen_int_mode ((HOST_WIDE_INT_1U << nbits) - 1,
+ <MODE>mode)));
+ DONE;
+ }
+
+ rtx src = operands[1];
+ if (trailing_bits != 0)
+ {
+ emit_insn (gen_ashl<mode>3 (operands[0],
+ operands[1],
+ GEN_INT (trailing_bits)));
+ src = operands[0];
+ }
+ emit_insn (gen_lshr<mode>3 (operands[0],
+ src,
+ GEN_INT (trailing_bits + bitpos)));
+ DONE;
+})
+
+;; Bit-field insert.
+(define_expand "insv<mode>"
+ [(set (zero_extract:QISI
+ (match_operand:QISI 0 "register_operand")
+ (match_operand:QISI 1 "const_int_operand")
+ (match_operand:QISI 2 "const_int_operand"))
+ (match_operand:QISI 3 "reg_or_ubyte_operand"))]
+ ""
+{
+ const int nbits = INTVAL (operands[1]);
+ const int bitpos = INTVAL (operands[2]);
+ if (nbits == 1)
+ {
+ rtx j;
+ rtx src = gen_reg_rtx (<MODE>mode);
+ rtx dst = operands[0];
+
+ emit_move_insn (src, operands[3]);
+
+ emit_insn (gen_and<mode>3 (dst,
+ dst,
+ gen_int_mode (~(HOST_WIDE_INT_1U << bitpos),
+ <MODE>mode)));
+
+ rtx_code_label *skip_set_label = gen_label_rtx ();
+ j = emit_jump_insn (gen_cbranch_qbbx_eq<mode><mode><mode>4 (
+ src,
+ GEN_INT (0),
+ skip_set_label));
+ JUMP_LABEL (j) = skip_set_label;
+ LABEL_NUSES (skip_set_label)++;
+
+ emit_insn (gen_ior<mode>3 (dst,
+ dst,
+ gen_int_mode (HOST_WIDE_INT_1U << bitpos,
+ <MODE>mode)));
+ emit_label (skip_set_label);
+
+ DONE;
+ }
+
+ /* Explicitly expand in order to avoid using word_mode for PRU, and instead
+ use SI and HI modes as applicable. */
+ rtx dst = operands[0];
+ rtx src = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_and<mode>3 (src,
+ force_reg (<MODE>mode, operands[3]),
+ gen_int_mode ((HOST_WIDE_INT_1U << nbits) - 1,
+ <MODE>mode)));
+ if (bitpos > 0)
+ emit_insn (gen_ashl<mode>3 (src, src, gen_int_mode (bitpos, <MODE>mode)));
+
+ HOST_WIDE_INT vmask = ~(((HOST_WIDE_INT_1U << nbits) - 1) << bitpos);
+ emit_insn (gen_and<mode>3 (dst,
+ dst,
+ gen_int_mode (vmask, <MODE>mode)));
+
+ emit_insn (gen_ior<mode>3 (dst, dst, src));
+
+ DONE;
+})
\f
;; Arithmetic Operations
diff --git a/gcc/testsuite/gcc.target/pru/ashiftrt.c b/gcc/testsuite/gcc.target/pru/ashiftrt.c
index ee8d55d60e6..fb8e4759a0e 100644
--- a/gcc/testsuite/gcc.target/pru/ashiftrt.c
+++ b/gcc/testsuite/gcc.target/pru/ashiftrt.c
@@ -8,6 +8,6 @@ extern void func2(unsigned char);
void test(unsigned char v)
{
- /* { dg-final { scan-assembler "lsl\tr14.b0, r14.b0, .\+\n\tlsr\tr14.b0, r14.b0" } } */
+ /* { dg-final { scan-assembler "lsr\tr14(.b0)?, r14.b0, .\+\n\tand\tr14.b0, r14.b0" } } */
func2((v & 2) ? 1 : 0);
}
diff --git a/gcc/testsuite/gcc.target/pru/extzv-1.c b/gcc/testsuite/gcc.target/pru/extzv-1.c
new file mode 100644
index 00000000000..573ded99830
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/extzv-1.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 12 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+unsigned int test(struct S s)
+{
+ return s.a;
+}
diff --git a/gcc/testsuite/gcc.target/pru/extzv-2.c b/gcc/testsuite/gcc.target/pru/extzv-2.c
new file mode 100644
index 00000000000..e34ba138f16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/extzv-2.c
@@ -0,0 +1,15 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 12 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 24;
+ unsigned int d : 2;
+};
+
+unsigned int test(struct S s)
+{
+ return s.d;
+}
diff --git a/gcc/testsuite/gcc.target/pru/extzv-3.c b/gcc/testsuite/gcc.target/pru/extzv-3.c
new file mode 100644
index 00000000000..66f4f376885
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/extzv-3.c
@@ -0,0 +1,13 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 16 } } */
+
+struct S {
+ unsigned int a : 9;
+ unsigned int b : 4;
+};
+
+unsigned int test(struct S s)
+{
+ return s.b;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-1.c b/gcc/testsuite/gcc.target/pru/insv-1.c
new file mode 100644
index 00000000000..50e29a1b818
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-1.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 16 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+void test(struct S *s)
+{
+ s->b = 1;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-2.c b/gcc/testsuite/gcc.target/pru/insv-2.c
new file mode 100644
index 00000000000..50272b713e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-2.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 16 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+void test(struct S *s)
+{
+ s->b = 0;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-3.c b/gcc/testsuite/gcc.target/pru/insv-3.c
new file mode 100644
index 00000000000..5ff0feb2ca1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-3.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 24 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+void test(struct S *s, unsigned int val)
+{
+ s->b = val;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-4.c b/gcc/testsuite/gcc.target/pru/insv-4.c
new file mode 100644
index 00000000000..4eaa733c560
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-4.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 28 } } */
+
+struct S {
+ unsigned int a : 3;
+ unsigned int b : 3;
+ unsigned int c : 3;
+};
+
+void test(struct S *s, unsigned int val)
+{
+ s->b = val;
+}
--
2.45.0
next prev parent reply other threads:[~2024-05-07 7:23 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 1/9] pru: Implement TARGET_ADDRESS_COST Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 2/9] pru: Implement zero fill for 64-bit registers Dimitar Dimitrov
2024-05-07 7:22 ` Dimitar Dimitrov [this message]
2024-05-07 7:22 ` [COMMITTED 4/9] pru: Add pattern variants for zero extending destination Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 5/9] pru: Skip register save if function will not return Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 6/9] pru: Drop usage of ATTRIBUTE_UNUSED Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 7/9] pru: Use HOST_WIDE_INT_1U macro Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 8/9] pru: Refactor to use passes definition file Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 9/9] pru: New validation pass for minrt Dimitar Dimitrov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=974fb8bda715b7fc8b2f3f9e227bf9b516a22a53.1715065537.git.dimitar@dinux.eu \
--to=dimitar@dinux.eu \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).