From 4de3604e01d43aa4921b2be78a5c86534806a24f Mon Sep 17 00:00:00 2001 From: Xionghu Luo Date: Mon, 20 Jul 2020 22:37:30 -0500 Subject: [PATCH] rs6000: Define movsf_from_si2 to extract high part SF element from DImode[PR89310] For extracting high part element from DImode register like: {%1:SF=unspec[r122:DI>>0x20#0] 86;clobber scratch;} split it before reload with "and mask" to avoid generating shift right 32 bit then shift left 32 bit. This pattern also exists in PR42475 and PR67741, etc. srdi 3,3,32 sldi 9,3,32 mtvsrd 1,9 xscvspdpn 1,1 => rldicr 3,3,0,31 mtvsrd 1,3 xscvspdpn 1,1 Bootstrap and regression tested pass on Power8-LE. gcc/ChangeLog: 2020-07-21 Xionghu Luo PR rtl-optimization/89310 * config/rs6000/rs6000.md (movsf_from_si2): New define_insn_and_split. gcc/testsuite/ChangeLog: 2020-07-21 Xionghu Luo PR rtl-optimization/89310 * gcc.target/powerpc/pr89310.c: New test. --- gcc/config/rs6000/rs6000.md | 31 ++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr89310.c | 17 ++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr89310.c diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index b3fcb845a389..97d690de7f2c 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -7634,6 +7634,37 @@ "*, *, p9v, p8v, *, *, p8v, p8v, p8v, *")]) +;; For extracting high part element from DImode register like: +;; {%1:SF=unspec[r122:DI>>0x20#0] 86;clobber scratch;} +;; split it before reload with "and mask" to avoid generating shift right +;; 32 bit then shift left 32 bit. +(define_insn_and_split "movsf_from_si2" + [(set (match_operand:SF 0 "gpc_reg_operand" "=wa") + (unspec:SF + [(subreg:SI + (ashiftrt:DI + (match_operand:DI 1 "input_operand" "r") + (const_int 32)) + 0)] + UNSPEC_SF_FROM_SI)) + (clobber (match_scratch:DI 2 "=r"))] + "TARGET_NO_SF_SUBREG" + "#" + "&& 1" + [(const_int 0)] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (DImode); + + rtx mask = GEN_INT (HOST_WIDE_INT_M1U << 32); + emit_insn (gen_anddi3 (operands[2], operands[1], mask)); + emit_insn (gen_p8_mtvsrd_sf (operands[0], operands[2])); + emit_insn (gen_vsx_xscvspdpn_directmove (operands[0], operands[0])); + DONE; +} + [(set_attr "length" "12") + (set_attr "type" "vecfloat") + (set_attr "isa" "p8v")]) ;; Move 64-bit binary/decimal floating point (define_expand "mov" diff --git a/gcc/testsuite/gcc.target/powerpc/pr89310.c b/gcc/testsuite/gcc.target/powerpc/pr89310.c new file mode 100644 index 000000000000..8bb1a1408242 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr89310.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power8 " } */ + +struct s { + int i; + float f; +}; + +float +foo (struct s arg) +{ + return arg.f; +} + +/* { dg-final { scan-assembler-not {\msrdi\M} } } */ +/* { dg-final { scan-assembler-not {\msldi\M} {target le} } } */ +/* { dg-final { scan-assembler-times {\mrldicr\M} 1 {target le} } } */ -- 2.47.2