diff options
author | Jiufu Guo <guojiufu@linux.ibm.com> | 2023-09-28 17:34:45 +0800 |
---|---|---|
committer | guojiufu <guojiufu@linux.ibm.com> | 2023-10-07 15:57:38 +0800 |
commit | 537d7a445ca0ed677751afd3cdcf8465ccd5fb7e (patch) | |
tree | fb3c39a3b7ad3324f6e5214321b7eb94131be8fd | |
parent | 5f56b76ff1c15118200204569389f85cca4e32d3 (diff) | |
download | gcc-537d7a445ca0ed677751afd3cdcf8465ccd5fb7e.zip gcc-537d7a445ca0ed677751afd3cdcf8465ccd5fb7e.tar.gz gcc-537d7a445ca0ed677751afd3cdcf8465ccd5fb7e.tar.bz2 |
rs6000: use mtvsrws to move sf from si p9
As mentioned in PR108338, on p9, we could use mtvsrws to implement
the bitcast from SI to SF (or lowpart DI to SF).
For example:
*(long long*)buff = di;
float f = *(float*)(buff);
"sldi 9,3,32 ; mtvsrd 1,9 ; xscvspdpn 1,1" is generated.
A better one would be "mtvsrws 1,3 ; xscvspdpn 1,1".
PR target/108338
gcc/ChangeLog:
* config/rs6000/rs6000.md (movsf_from_si): Update to generate mtvsrws
for P9.
gcc/testsuite/ChangeLog:
* gcc.target/powerpc/pr108338.c: Updated to check mtvsrws for p9.
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/pr108338.c | 21 |
2 files changed, 37 insertions, 9 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 8e7edfc..96084c1 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -8309,13 +8309,26 @@ { rtx op0 = operands[0]; rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx op1_di = gen_rtx_REG (DImode, REGNO (op1)); - /* Move SF value to upper 32-bits for xscvspdpn. */ - emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32))); - emit_insn (gen_p8_mtvsrd_sf (op0, op2)); - emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0)); + /* Move lowpart 32-bits from register for SFmode. */ + if (TARGET_P9_VECTOR) + { + /* Using mtvsrws;xscvspdpn. */ + rtx op0_v = gen_rtx_REG (V4SImode, REGNO (op0)); + emit_insn (gen_vsx_splat_v4si (op0_v, op1)); + emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0)); + } + else + { + rtx op2 = operands[2]; + rtx op1_di = gen_rtx_REG (DImode, REGNO (op1)); + + /* Using sldi;mtvsrd;xscvspdpn. */ + emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32))); + emit_insn (gen_p8_mtvsrd_sf (op0, op2)); + emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0)); + } + DONE; } [(set_attr "length" diff --git a/gcc/testsuite/gcc.target/powerpc/pr108338.c b/gcc/testsuite/gcc.target/powerpc/pr108338.c index bd83c0b..5f2f628 100644 --- a/gcc/testsuite/gcc.target/powerpc/pr108338.c +++ b/gcc/testsuite/gcc.target/powerpc/pr108338.c @@ -3,9 +3,12 @@ /* { dg-options "-O2 -save-temps" } */ /* Under lp64, parameter 'v' is in DI regs, then bitcast sub DI to SF. */ -/* { dg-final { scan-assembler-times {\mxscvspdpn\M} 1 { target { lp64 && has_arch_pwr8 } } } } */ -/* { dg-final { scan-assembler-times {\mmtvsrd\M} 1 { target { lp64 && has_arch_pwr8 } } } } */ +/* { dg-final { scan-assembler-times {\mxscvspdpn\M} 2 { target { lp64 && has_arch_pwr8 } } } } */ +/* { dg-final { scan-assembler-times {\mmtvsrd\M} 2 { target { lp64 && { has_arch_pwr8 && { ! has_arch_pwr9 } } } } } } */ +/* { dg-final { scan-assembler-times {\mmtvsrd\M} 1 { target { lp64 && has_arch_pwr9 } } } } */ +/* { dg-final { scan-assembler-times {\mmtvsrws\M} 1 { target { lp64 && has_arch_pwr9 } } } } */ /* { dg-final { scan-assembler-times {\mrldicr\M} 1 { target { lp64 && has_arch_pwr8 } } } } */ +/* { dg-final { scan-assembler-times {\msldi\M} 1 { target { lp64 && { has_arch_pwr8 && { ! has_arch_pwr9 } } } } } } */ struct di_sf_sf { @@ -22,16 +25,28 @@ sf_from_high32bit_di (struct di_sf_sf v) #endif } +float __attribute__ ((noipa)) +sf_from_low32bit_di (struct di_sf_sf v) +{ +#ifdef __LITTLE_ENDIAN__ + return v.f1; +#else + return v.f2; +#endif +} + int main() { struct di_sf_sf v; v.f1 = v.f2 = 0.0f; #ifdef __LITTLE_ENDIAN__ + v.f1 = 1.0f; v.f2 = 2.0f; #else v.f1 = 2.0f; + v.f2 = 1.0f; #endif - if (sf_from_high32bit_di (v) != 2.0f) + if (sf_from_high32bit_di (v) != 2.0f || sf_from_low32bit_di (v) != 1.0f) __builtin_abort (); return 0; } |