[Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
authorJames Greenhalgh <james.greenhalgh@arm.com>
Thu, 24 Nov 2016 18:14:36 +0000 (18:14 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Thu, 24 Nov 2016 18:14:36 +0000 (18:14 +0000)
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

gcc/ChangeLog
gcc/config/aarch64/aarch64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c [new file with mode: 0644]

index ca7155d..f142c46 100644 (file)
@@ -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
index 3d21232..26982f6 100644 (file)
   [(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"
   [(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"
index 96c5957..12a17c9 100644 (file)
@@ -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 (file)
index 0000000..9eaa4ba
--- /dev/null
@@ -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" } } */