aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJames Greenhalgh <james.greenhalgh@arm.com>2016-11-24 18:14:36 +0000
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>2016-11-24 18:14:36 +0000
commitbf1e3646d150a0fcb542c918ad381f9aee583633 (patch)
treedc6f4d854dc0606b3243ce9d9d162180eb0edc5e /gcc
parente210b51b58d1431b7f710e7eac00bd9c128632b3 (diff)
downloadgcc-bf1e3646d150a0fcb542c918ad381f9aee583633.zip
gcc-bf1e3646d150a0fcb542c918ad381f9aee583633.tar.gz
gcc-bf1e3646d150a0fcb542c918ad381f9aee583633.tar.bz2
[Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
gcc/ * config/aarch64/aarch64.md (<optab>sihf2): Convert to expand. (<optab>dihf2): Likewise. (aarch64_fp16_<optab><mode>hf2): New. gcc/testsuite/ * gcc.target/aarch64/floatdihf2_1.c: New. From-SVN: r242843
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/aarch64/aarch64.md56
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c35
4 files changed, 100 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ca7155d..f142c46 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2016-11-24 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.md (<optab>sihf2): Convert to expand.
+ (<optab>dihf2): Likewise.
+ (aarch64_fp16_<optab><mode>hf2): New.
+
2016-11-24 Alexander Monakov <amonakov@ispras.ru>
PR target/67822
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 3d21232..26982f6 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4652,7 +4652,14 @@
[(set_attr "type" "f_cvti2f")]
)
-(define_insn "<optab><mode>hf2"
+;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
+;; midend will arrange for an SImode conversion to HFmode to first go
+;; through DFmode, then to HFmode. But first it will try converting
+;; to DImode then down, which would match our DImode pattern below and
+;; give very poor code-generation. So, we must provide our own emulation
+;; of the mid-end logic.
+
+(define_insn "aarch64_fp16_<optab><mode>hf2"
[(set (match_operand:HF 0 "register_operand" "=w")
(FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
"TARGET_FP_F16INST"
@@ -4660,6 +4667,53 @@
[(set_attr "type" "f_cvti2f")]
)
+(define_expand "<optab>sihf2"
+ [(set (match_operand:HF 0 "register_operand")
+ (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
+ "TARGET_FLOAT"
+{
+ if (TARGET_FP_F16INST)
+ emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
+ else
+ {
+ rtx convert_target = gen_reg_rtx (DFmode);
+ emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
+ emit_insn (gen_truncdfhf2 (operands[0], convert_target));
+ }
+ DONE;
+}
+)
+
+;; For DImode there is no wide enough floating-point mode that we
+;; can convert through natively (TFmode would work, but requires a library
+;; call). However, we know that any value >= 65504 will be rounded
+;; to infinity on conversion. This is well within the range of SImode, so
+;; we can:
+;; Saturate to SImode.
+;; Convert from that to DFmode
+;; Convert from that to HFmode (phew!).
+;; Note that the saturation to SImode requires the SIMD extensions. If
+;; we ever need to provide this pattern where the SIMD extensions are not
+;; available, we would need a different approach.
+
+(define_expand "<optab>dihf2"
+ [(set (match_operand:HF 0 "register_operand")
+ (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
+ "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
+{
+ if (TARGET_FP_F16INST)
+ emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
+ else
+ {
+ rtx sat_target = gen_reg_rtx (SImode);
+ emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
+ emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
+ }
+
+ DONE;
+}
+)
+
;; Convert between fixed-point and floating-point (scalar modes)
(define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 96c5957..12a17c9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2016-11-24 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * gcc.target/aarch64/floatdihf2_1.c: New.
+
2016-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/48863
diff --git a/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c b/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c
new file mode 100644
index 0000000..9eaa4ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* Test that conversion from 32-bit and 64-bit integers can be done
+ without a call to the support library. */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+__fp16
+foo (int x)
+{
+ return x;
+}
+
+__fp16
+bar (unsigned int x)
+{
+ return x;
+}
+
+__fp16
+fool (long long x)
+{
+ return x;
+}
+
+__fp16
+barl (unsigned long long x)
+{
+ return x;
+}
+
+
+/* { dg-final { scan-assembler-not "__float\\\[ds\\\]ihf2" } } */
+/* { dg-final { scan-assembler-not "__floatun\\\[ds\\\]ihf2" } } */