diff options
author | Maciej W. Rozycki <macro@orcam.me.uk> | 2024-12-25 22:23:39 +0000 |
---|---|---|
committer | Maciej W. Rozycki <macro@orcam.me.uk> | 2024-12-25 22:23:39 +0000 |
commit | 3c99ea19d26a2458302c54a33fbd17abfbef787a (patch) | |
tree | 625e31900af54d434869ff06bdec8ebe828c55e1 | |
parent | 665e0f9c08a9922ba06aeaa719fd4adc5a689df7 (diff) | |
download | gcc-3c99ea19d26a2458302c54a33fbd17abfbef787a.zip gcc-3c99ea19d26a2458302c54a33fbd17abfbef787a.tar.gz gcc-3c99ea19d26a2458302c54a33fbd17abfbef787a.tar.bz2 |
Alpha: Permit constant zero source for "insvmisaligndi"
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.
-rw-r--r-- | gcc/config/alpha/alpha.md | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/alpha/stlx0.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/alpha/stqx0.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/alpha/stwx0-bwx.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/alpha/stwx0.c | 28 |
5 files changed, 104 insertions, 1 deletions
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 22ea4db..2faa942 100644 --- a/gcc/config/alpha/alpha.md +++ b/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. */ diff --git a/gcc/testsuite/gcc.target/alpha/stlx0.c b/gcc/testsuite/gcc.target/alpha/stlx0.c new file mode 100644 index 0000000..876eceb --- /dev/null +++ b/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" } } */ diff --git a/gcc/testsuite/gcc.target/alpha/stqx0.c b/gcc/testsuite/gcc.target/alpha/stqx0.c new file mode 100644 index 0000000..042cdf0 --- /dev/null +++ b/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" } } */ diff --git a/gcc/testsuite/gcc.target/alpha/stwx0-bwx.c b/gcc/testsuite/gcc.target/alpha/stwx0-bwx.c new file mode 100644 index 0000000..bba31df --- /dev/null +++ b/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 } } */ diff --git a/gcc/testsuite/gcc.target/alpha/stwx0.c b/gcc/testsuite/gcc.target/alpha/stwx0.c new file mode 100644 index 0000000..d60d33f --- /dev/null +++ b/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" } } */ |