aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiufu Guo <guojiufu@linux.ibm.com>2023-09-28 17:34:45 +0800
committerguojiufu <guojiufu@linux.ibm.com>2023-10-07 15:57:38 +0800
commit537d7a445ca0ed677751afd3cdcf8465ccd5fb7e (patch)
treefb3c39a3b7ad3324f6e5214321b7eb94131be8fd
parent5f56b76ff1c15118200204569389f85cca4e32d3 (diff)
downloadgcc-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.md25
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr108338.c21
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;
}