aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKewen Lin <linkw@linux.ibm.com>2021-06-11 02:43:40 -0500
committerKewen Lin <linkw@linux.ibm.com>2021-06-11 02:43:40 -0500
commit2f5ab546e2be8e42b00416b2e5860d04a881beab (patch)
tree79f25bdb5d52ac9094f39b98bf00d5ed464922cb /gcc
parente9d322ced1433da8e7c69243cfa941ea462d6290 (diff)
downloadgcc-2f5ab546e2be8e42b00416b2e5860d04a881beab.zip
gcc-2f5ab546e2be8e42b00416b2e5860d04a881beab.tar.gz
gcc-2f5ab546e2be8e42b00416b2e5860d04a881beab.tar.bz2
rs6000: Support more short/char to float conversion
For some cases that when we load unsigned char/short values from the appropriate unsigned char/short memories and convert them to double/single precision floating point value, there would be implicit conversions to int first. It makes GCC not leverage the P9 instructions lxsibzx/lxsihzx. This patch is to add the related define_insn_and_split to support this kind of scenario. Bootstrapped/regtested on powerpc64le-linux-gnu P9 and powerpc64-linux-gnu P8. gcc/ChangeLog: * config/rs6000/rs6000.md (floatsi<SFDF:mode>2_lfiwax_<QHI:mode>_mem_zext): New define_insn_and_split. gcc/testsuite/ChangeLog: * gcc.target/powerpc/p9-fpcvt-3.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.md21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-fpcvt-3.c23
2 files changed, 44 insertions, 0 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 89c70f4..510dbff 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -5524,6 +5524,27 @@
[(set_attr "length" "8")
(set_attr "type" "fpload")])
+(define_insn_and_split "floatsi<SFDF:mode>2_lfiwax_<QHI:mode>_mem_zext"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<Fv>")
+ (float:SFDF
+ (zero_extend:SI
+ (match_operand:QHI 1 "indexed_or_indirect_operand" "Z,Z"))))
+ (clobber (match_scratch:DI 2 "=d,wa"))]
+ "TARGET_HARD_FLOAT && <SI_CONVERT_FP> && TARGET_P9_VECTOR
+ && TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+ "#"
+ "&& 1"
+ [(pc)]
+{
+ if (GET_CODE (operands[2]) == SCRATCH)
+ operands[2] = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendhidi2 (operands[2], operands[1]));
+ emit_insn (gen_floatdi<SFDF:mode>2 (operands[0], operands[2]));
+ DONE;
+}
+ [(set_attr "length" "8")
+ (set_attr "type" "fpload")])
+
(define_insn "lfiwzx"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d,wa,wa,wa")
(unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wa")]
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-3.c b/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-3.c
new file mode 100644
index 0000000..19701c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-3.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target lp64 } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
+
+/* Note that for unsigned cases, the differences from those ones in
+ p9-fpcvt-2.c is that they will be converted to int implicitly first
+ and then to floating point. */
+
+double sc_df (signed char *p, double df) { return *p + df; }
+double uc_df (unsigned char *p, double df) { return *p + df; }
+double ss_df (signed short *p, double df) { return *p + df; }
+double us_df (unsigned short *p, double df) { return *p + df; }
+
+float sc_sf (signed char *p, float sf) { return *p + sf; }
+float uc_sf (unsigned char *p, float sf) { return *p + sf; }
+float ss_sf (signed short *p, float sf) { return *p + sf; }
+float us_sf (unsigned short *p, float sf) { return *p + sf; }
+
+/* { dg-final { scan-assembler {\mlxsibzx\M} } } */
+/* { dg-final { scan-assembler {\mlxsihzx\M} } } */
+/* { dg-final { scan-assembler {\mvextsb2d\M} } } */
+/* { dg-final { scan-assembler {\mvextsh2d\M} } } */
+/* { dg-final { scan-assembler-not {\mm[tf]vsr} } } */