rs6000: Define movsf_from_si2 to extract high part SF element from DImode[PR89310]
authorXionghu Luo <luoxhu@linux.ibm.com>
Tue, 21 Jul 2020 03:37:30 +0000 (22:37 -0500)
committerXionghu Luo <luoxhu@linux.ibm.com>
Tue, 21 Jul 2020 03:37:30 +0000 (22:37 -0500)
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  <luoxhu@linux.ibm.com>

PR rtl-optimization/89310
* config/rs6000/rs6000.md (movsf_from_si2): New define_insn_and_split.

gcc/testsuite/ChangeLog:

2020-07-21  Xionghu Luo  <luoxhu@linux.ibm.com>

PR rtl-optimization/89310
* gcc.target/powerpc/pr89310.c: New test.

gcc/config/rs6000/rs6000.md
gcc/testsuite/gcc.target/powerpc/pr89310.c [new file with mode: 0644]

index b3fcb845a389bf827798fb8b97f42148979204be..97d690de7f2c4d0a6fafa787d5d1e732cd9c481b 100644 (file)
            "*,          *,         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")])
 \f
 ;; Move 64-bit binary/decimal floating point
 (define_expand "mov<mode>"
diff --git a/gcc/testsuite/gcc.target/powerpc/pr89310.c b/gcc/testsuite/gcc.target/powerpc/pr89310.c
new file mode 100644 (file)
index 0000000..8bb1a14
--- /dev/null
@@ -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} } } */