From 537d7a445ca0ed677751afd3cdcf8465ccd5fb7e Mon Sep 17 00:00:00 2001 From: Jiufu Guo Date: Thu, 28 Sep 2023 17:34:45 +0800 Subject: 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. --- gcc/config/rs6000/rs6000.md | 25 +++++++++++++++++++------ 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; } -- cgit v1.1