]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
pru: Add pattern variants for zero extending destination
authorDimitar Dimitrov <dimitar@dinux.eu>
Fri, 29 Dec 2023 19:22:58 +0000 (21:22 +0200)
committerDimitar Dimitrov <dimitar@dinux.eu>
Tue, 7 May 2024 07:17:27 +0000 (10:17 +0300)
The higher bits in the result of some ALU operations are inherently
always zero when all input operands are smaller than 32-bits.

Add pattern variants to match when the resulting value is zero
extended, so that all operations can be effectively executed in a
single instruction.  For PRU it simply means to use a wider register for
destination.

ALU operations which cannot be presented as zero-extending their
destination are addition, subtraction and logical shift left.  The PRU
ALU performs all operations in 32-bit mode, so the carry-out and
shifted-out bits would violate the assumption that ALU operation was
performed in 16-bit or 8-bit mode, and result was zero-extended.

gcc/ChangeLog:

* config/pru/alu-zext.md (_noz0): New subst attribute.
(<code>_impl): Allow zero-extending the destination.
(<shift_op>): Remove unified pattern
(ashl_impl): New distinct pattern.
(lshr_impl): Ditto.
(alu3_zext_op0_subst): New subst iterator to zero-extend the
destination register.

gcc/testsuite/ChangeLog:

* gcc.target/pru/extzv-1.c: Update to mark the new more
efficient generated code sequence.
* gcc.target/pru/extzv-2.c: Ditto.
* gcc.target/pru/extzv-3.c: Ditto.
* gcc.target/pru/zero_extend-op0.c: New test.

Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
gcc/config/pru/alu-zext.md
gcc/testsuite/gcc.target/pru/extzv-1.c
gcc/testsuite/gcc.target/pru/extzv-2.c
gcc/testsuite/gcc.target/pru/extzv-3.c
gcc/testsuite/gcc.target/pru/zero_extend-op0.c [new file with mode: 0644]

index 04378db4774a4d9c58c1c47bc80945ebf1bf8851..c88eaf0ab44cf05a1a190492bcb9736e0e377c4f 100644 (file)
@@ -33,6 +33,7 @@
 
 (define_subst_attr "alu2_zext"     "alu2_zext_subst"     "_z" "_noz")
 
+(define_subst_attr "alu3_zext_op0" "alu3_zext_op0_subst" "_z0" "_noz0")
 (define_subst_attr "alu3_zext_op1" "alu3_zext_op1_subst" "_z1" "_noz1")
 (define_subst_attr "alu3_zext_op2" "alu3_zext_op2_subst" "_z2" "_noz2")
 (define_subst_attr "alu3_zext"     "alu3_zext_subst"     "_z" "_noz")
@@ -44,6 +45,7 @@
 (define_subst_attr "bitalu_zext"   "bitalu_zext_subst"   "_z" "_noz")
 
 (define_code_iterator ALUOP3 [plus minus and ior xor umin umax ashift lshiftrt])
+(define_code_iterator ALUOP3_ZEXT0 [and ior xor umin umax lshiftrt])
 (define_code_iterator ALUOP2 [neg not])
 
 ;; Arithmetic Operations
   "set\\t%0, %1, %T2"
   [(set_attr "type" "alu")])
 
-; Regular ALU ops
-(define_insn "<code>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+; Regular ALU ops.  For all of them it is safe to present the result as
+; zero-extended, because there is no carry or shifted-out bits.
+(define_insn "<code>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op0><alu3_zext_op1><alu3_zext_op2>"
   [(set (match_operand:EQD 0 "register_operand" "=r")
        (LOGICAL:EQD
          (zero_extend:EQD
   "<logical_asm>\\t%0, %1, %u2"
   [(set_attr "type" "alu")])
 
-; Shift ALU ops
-(define_insn "<shift_op>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+; Shift left ALU op.  Cannot present the result as zero-extended because
+; of the shifted-out bits.
+(define_insn "ashl_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
   [(set (match_operand:EQD 0 "register_operand" "=r")
-       (SHIFT:EQD
+       (ashift:EQD
         (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))
         (zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"))))]
   ""
-  "<shift_asm>\\t%0, %1, %2"
+  "lsl\\t%0, %1, %2"
+  [(set_attr "type" "alu")])
+
+; Shift right ALU op.  The result can be presented as zero-extended.
+(define_insn "lshr_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op0><alu3_zext_op1><alu3_zext_op2>"
+  [(set (match_operand:EQD 0 "register_operand" "=r")
+       (lshiftrt:EQD
+        (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))
+        (zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"))))]
+  ""
+  "lsr\\t%0, %1, %2"
   [(set_attr "type" "alu")])
 
 ;; Substitutions
        (ALUOP3:EQD (zero_extend:EQD (match_dup 1))
                    (match_dup 2)))])
 
+;; Some ALU operations with zero-extended inputs are
+;; equivalent to doing the same ALU operation in the
+;; smaller mode, and then zero-extending the output.
+(define_subst "alu3_zext_op0_subst"
+  [(set (match_operand:EQD 0)
+       (ALUOP3_ZEXT0:EQD (zero_extend:EQD (match_operand:EQS0 1))
+                         (zero_extend:EQD (match_operand:EQS0 2))))]
+  "GET_MODE_SIZE (<EQS0:MODE>mode) < GET_MODE_SIZE (<EQD:MODE>mode)"
+  [(set (match_dup 0)
+       (zero_extend:EQD
+         (ALUOP3_ZEXT0:EQS0 (match_dup 1)
+                            (match_dup 2))))])
 
 (define_subst "lmbd_zext_subst"
   [(set (match_operand:EQD 0)
index 573ded99830b0d702d28d005e86e976c9e5a82a4..165e1d7108112cca1614e60c8a18c691e03e9508 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do assemble } */
 /* { dg-options "-Os" } */
-/* { dg-final { object-size text <= 12 } } */
+/* { dg-final { object-size text <= 8 } } */
 
 struct S {
     unsigned int a : 5;
index e34ba138f16f2ff7fbe2cae9d853f07d84e8192d..6ecf9170c94e854cc36e56fb6552bb807ff76b22 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do assemble } */
 /* { dg-options "-Os" } */
-/* { dg-final { object-size text <= 12 } } */
+/* { dg-final { object-size text <= 8 } } */
 
 struct S {
     unsigned int a : 5;
index 66f4f3768851bae2001822ecb4ed4a0a0883dde6..7799b8505afcc4ba8913557b516f25a830093155 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do assemble } */
 /* { dg-options "-Os" } */
-/* { dg-final { object-size text <= 16 } } */
+/* { dg-final { object-size text <= 12 } } */
 
 struct S {
     unsigned int a : 9;
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-op0.c b/gcc/testsuite/gcc.target/pru/zero_extend-op0.c
new file mode 100644 (file)
index 0000000..e9e86f7
--- /dev/null
@@ -0,0 +1,28 @@
+/* ALU operations with zero extended destination. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant.  Without it the zero extension might not
+   be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_xor_hi (unsigned short val1, unsigned short val2)
+{
+  /* { dg-final { scan-assembler "xor\\tr14, r14.w0, r14.w2" } } */
+  return (unsigned short)(val1 ^ val2);
+}
+
+unsigned int
+test_zext_or_hi (unsigned short val1, unsigned short val2)
+{
+  /* { dg-final { scan-assembler "or\\tr14, r14.w0, r14.w2" } } */
+  return (unsigned short)(val1 | val2);
+}
+
+unsigned int
+test_zext_ashr_hi_const (unsigned short val1)
+{
+  /* { dg-final { scan-assembler "lsr\\tr14, r14.w0, 3" } } */
+  return (unsigned short)(val1 >> 3);
+}