Eliminate a redundant bitwise inclusive OR operation on the insertion of 
constant zero into a bit-field, improving code produced at `-O2' from an 
output sequence such as:

        mov $31,$3                              # Redundant!
        ldq_u $1,7($16)
        insqh $3,$16,$3                         # Redundant!
        ldq_u $2,0($16)
        mskqh $1,$16,$1
        mskql $2,$16,$2
        bis $1,$3,$1                            # Redundant!
        stq_u $1,7($16)
        stq_u $2,0($16)
        ret $31,($26),1

to:

        ldq_u $2,7($16)
        ldq_u $1,0($16)
        mskqh $2,$16,$2
        stq_u $2,7($16)
        mskql $1,$16,$1
        stq_u $1,0($16)
        ret $31,($26),1

for a quadword unaligned store operation.  As shown in the example this 
only triggers for the high-part store (and therefore only for 2-byte, 
4-byte, and 8-byte stores), because `insXl' insns are fully expressed in 
terms of RTL and therefore the insertion of zero is eliminated in later 
RTL passes, however corresponding `insXh' insns are unspecs only, making 
them impossible to see through.

We can get this optimal right from expand though, given that our handler 
for "insvmisaligndi", i.e. `alpha_expand_unaligned_store', has explicit 
provisions for `const0_rtx' source.

        gcc/
        * config/alpha/alpha.md (insvmisaligndi): Use "reg_or_0_operand" 
        rather than "register_operand" for operand 3.

        gcc/testsuite/
        * gcc.target/alpha/stlx0.c: New file.
        * gcc.target/alpha/stqx0.c: New file.
        * gcc.target/alpha/stwx0.c: New file.
        * gcc.target/alpha/stwx0-bwx.c: New file.
---
 gcc/config/alpha/alpha.md                  |    2 +-
 gcc/testsuite/gcc.target/alpha/stlx0.c     |   28 ++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/alpha/stqx0.c     |   28 ++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/alpha/stwx0-bwx.c |   19 +++++++++++++++++++
 gcc/testsuite/gcc.target/alpha/stwx0.c     |   28 ++++++++++++++++++++++++++++
 5 files changed, 104 insertions(+), 1 deletion(-)

gcc-alpha-insvmisaligndi-zero.diff
Index: gcc/gcc/config/alpha/alpha.md
===================================================================
--- gcc.orig/gcc/config/alpha/alpha.md
+++ gcc/gcc/config/alpha/alpha.md
@@ -4626,7 +4626,7 @@
   [(set (zero_extract:DI (match_operand:BLK 0 "memory_operand")
                         (match_operand:DI 1 "const_int_operand")
                         (match_operand:DI 2 "const_int_operand"))
-       (match_operand:DI 3 "register_operand"))]
+       (match_operand:DI 3 "reg_or_0_operand"))]
   ""
 {
   /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries.  */
Index: gcc/gcc/testsuite/gcc.target/alpha/stlx0.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/alpha/stlx0.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+typedef struct { int v __attribute__ ((packed)); } intx;
+
+void
+stlx0 (intx *p)
+{
+  p->v = 0;
+}
+
+/* Expect assembly such as:
+
+       ldq_u $2,3($16)
+       ldq_u $1,0($16)
+       msklh $2,$16,$2
+       stq_u $2,3($16)
+       mskll $1,$16,$1
+       stq_u $1,0($16)
+
+   without any INSLH, INSLL, or BIS instructions.  */
+
+/* { dg-final { scan-assembler-times "\\sldq_u\\s" 2 } } */
+/* { dg-final { scan-assembler-times "\\smsklh\\s" 1 } } */
+/* { dg-final { scan-assembler-times "\\smskll\\s" 1 } } */
+/* { dg-final { scan-assembler-times "\\sstq_u\\s" 2 } } */
+/* { dg-final { scan-assembler-not "\\s(?:bis|inslh|insll)\\s" } } */
Index: gcc/gcc/testsuite/gcc.target/alpha/stqx0.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/alpha/stqx0.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+typedef struct { long v __attribute__ ((packed)); } longx;
+
+void
+stqx0 (longx *p)
+{
+  p->v = 0;
+}
+
+/* Expect assembly such as:
+
+       ldq_u $2,7($16)
+       ldq_u $1,0($16)
+       mskqh $2,$16,$2
+       stq_u $2,7($16)
+       mskql $1,$16,$1
+       stq_u $1,0($16)
+
+   without any INSQH, INSQL, or BIS instructions.  */
+
+/* { dg-final { scan-assembler-times "\\sldq_u\\s" 2 } } */
+/* { dg-final { scan-assembler-times "\\smskqh\\s" 1 } } */
+/* { dg-final { scan-assembler-times "\\smskql\\s" 1 } } */
+/* { dg-final { scan-assembler-times "\\sstq_u\\s" 2 } } */
+/* { dg-final { scan-assembler-not "\\s(?:bis|insqh|insql)\\s" } } */
Index: gcc/gcc/testsuite/gcc.target/alpha/stwx0-bwx.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/alpha/stwx0-bwx.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-mbwx" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+typedef struct { short v __attribute__ ((packed)); } shortx;
+
+void
+stwx0 (shortx *p)
+{
+  p->v = 0;
+}
+
+/* Expect assembly such as:
+
+        stb $31,0($16)
+        stb $31,1($16)
+ */
+
+/* { dg-final { scan-assembler-times "\\sstb\\s\\\$31," 2 } } */
Index: gcc/gcc/testsuite/gcc.target/alpha/stwx0.c
===================================================================
--- /dev/null
+++ gcc/gcc/testsuite/gcc.target/alpha/stwx0.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-bwx" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+typedef struct { short v __attribute__ ((packed)); } shortx;
+
+void
+stwx0 (shortx *p)
+{
+  p->v = 0;
+}
+
+/* Expect assembly such as:
+
+       ldq_u $2,1($16)
+       ldq_u $1,0($16)
+       mskwh $2,$16,$2
+       stq_u $2,1($16)
+       mskwl $1,$16,$1
+       stq_u $1,0($16)
+
+   without any INSWH, INSWL, or BIS instructions.  */
+
+/* { dg-final { scan-assembler-times "\\sldq_u\\s" 2 } } */
+/* { dg-final { scan-assembler-times "\\smskwh\\s" 1 } } */
+/* { dg-final { scan-assembler-times "\\smskwl\\s" 1 } } */
+/* { dg-final { scan-assembler-times "\\sstq_u\\s" 2 } } */
+/* { dg-final { scan-assembler-not "\\s(?:bis|inswh|inswl)\\s" } } */

Reply via email to