gcc/ChangeLog:

        * config/i386/i386.md (*avx512fp16_1_roundhf2): New define_insn.
        * config/i386/sse.md (*avx512fp16_1_roundhf): New fine_insn.

gcc/testsuite/ChangeLog:

        * gcc.target/i386/avx512fp16-builtin-round-2.c: New test.
---
 gcc/config/i386/i386.md                       | 22 ++++++++++++++
 gcc/config/i386/sse.md                        | 20 +++++++++++++
 .../i386/avx512fp16-builtin-round-2.c         | 29 +++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-2.c

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 684b2080a93..457f37dcb61 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -17738,6 +17738,28 @@ (define_expand "significand<mode>2"
 })
 
 
+/* Optimize for code like (_Float16) __builtin_ceif ((float) f16)
+   since it's not handled in frontend.  */
+
+(define_insn "*avx512fp16_1_roundhf2"
+  [(set (match_operand:HF 0 "register_operand" "=v,v")
+       (float_truncate:HF
+         (unspec:MODEF
+           [(float_extend:MODEF
+               (match_operand:HF 1 "nonimmediate_operand" "v,m"))
+            (match_operand:SI 2 "const_0_to_15_operand" "n,n")]
+           UNSPEC_ROUND)))]
+  "TARGET_AVX512FP16"
+  "@
+   vrndscalesh\t{%2, %d1, %0|%0, %d1, %2}
+   vrndscalesh\t{%2, %1, %d0|%d0, %1, %2}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "length_immediate" "1,1")
+   (set_attr "prefix" "evex")
+   (set_attr "avx_partial_xmm_update" "false,true")
+   (set_attr "mode" "HF")])
+
+
 (define_insn "sse4_1_round<mode>2"
   [(set (match_operand:MODEFH 0 "register_operand" "=x,x,x,v,v")
        (unspec:MODEFH
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 2b8d12086f4..b3d8ffb4f8e 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -20220,6 +20220,26 @@ (define_insn "sse4_1_round<ssescalarmodesuffix>"
    (set_attr "prefix" "orig,orig,vex,evex")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "*avx512fp16_1_roundhf"
+  [(set (match_operand:V8HF 0 "register_operand" "=v")
+       (vec_merge:V8HF
+         (vec_duplicate:V8HF
+           (float_truncate:HF
+             (unspec:MODEF
+               [(float_extend:MODEF
+                  (match_operand:HF 2 "nonimmediate_operand" "vm"))
+                (match_operand:SI 3 "const_0_to_15_operand" "n")]
+             UNSPEC_ROUND)))
+         (match_operand:V8HF 1 "register_operand" "v")
+         (const_int 1)))]
+  "TARGET_AVX512FP16"
+  "vrndscalesh\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "length_immediate" "1")
+   (set_attr "prefix_extra" "1")
+   (set_attr "prefix" "evex")
+   (set_attr "mode" "HF")])
+
 (define_insn "*sse4_1_round<ssescalarmodesuffix>"
   [(set (match_operand:VFH_128 0 "register_operand" "=Yr,*x,x,v")
        (vec_merge:VFH_128
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-2.c 
b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-2.c
new file mode 100644
index 00000000000..bcd41929637
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-builtin-round-2.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512fp16" } */
+
+_Float16
+foo1 (_Float16 a)
+{
+  return __builtin_roundeven (a);
+}
+
+_Float16
+foo2 (_Float16 a)
+{
+  return __builtin_trunc (a);
+}
+
+_Float16
+foo3 (_Float16 a)
+{
+  return __builtin_ceil (a);
+}
+
+_Float16
+foo4 (_Float16 a)
+{
+  return __builtin_floor (a);
+}
+
+/* { dg-final { scan-assembler-not "vcvtsh2s\[sd\]" } } */
+/* { dg-final { scan-assembler-times "vrndscalesh\[^\n\r\]*xmm\[0-9\]" 4 } } */
-- 
2.18.1

Reply via email to