aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorXionghu Luo <luoxhu@linux.ibm.com>2020-07-20 22:37:30 -0500
committerXionghu Luo <luoxhu@linux.ibm.com>2020-07-20 22:37:30 -0500
commit2ef4cf87a7c7f36c1fe523e4d71bbb4846ab0c35 (patch)
tree32c3cc10dbba925faab4cf80396f57ee3929034b /gcc
parent41efe9812a5df22201c3a684ff2fb838d6dc9de6 (diff)
downloadgcc-2ef4cf87a7c7f36c1fe523e4d71bbb4846ab0c35.zip
gcc-2ef4cf87a7c7f36c1fe523e4d71bbb4846ab0c35.tar.gz
gcc-2ef4cf87a7c7f36c1fe523e4d71bbb4846ab0c35.tar.bz2
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 <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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.md31
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr89310.c17
2 files changed, 48 insertions, 0 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index b3fcb84..97d690d 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<mode>"
diff --git a/gcc/testsuite/gcc.target/powerpc/pr89310.c b/gcc/testsuite/gcc.target/powerpc/pr89310.c
new file mode 100644
index 0000000..8bb1a14
--- /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} } } */