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