From: Kyrylo Tkachov <[email protected]>
FEAT_FP16 provides half-precision forms of FCCMP and FCCMPE. The
conditional-compare patterns and expansion hooks currently accept only
SFmode and DFmode comparisons. For example, with -O2 -fno-trapping-math
-march=armv8.2-a+fp16:
int
f (_Float16 a, _Float16 b, _Float16 c, _Float16 d)
{
return (a == b) && (c == d);
}
AArch64 emitted:
fcmp h0, h1
cset w1, eq
fcmp h2, h3
cset w0, eq
and w0, w1, w0
After this patch it emits:
fcmp h0, h1
fccmp h2, h3, 0, eq
cset w0, eq
Use GPF_F16 for both conditional-compare patterns. Use the stype attribute
so HFmode keeps the single-precision scheduling type. Teach both expansion
hooks to select HFmode, and reject it when FEAT_FP16 is not available.
The tests also cover FCCMPE, the reverse pattern used by OR expressions, and
+nofp16.
Bootstrapped and tested on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill
gcc/
* config/aarch64/aarch64.cc (aarch64_gen_ccmp_first): Handle HFmode.
(aarch64_gen_ccmp_next): Likewise. Reject unsupported HFmode early.
* config/aarch64/aarch64.md
(@ccmp<CCFP_CCFPE:mode><GPF_F16:mode>): Use GPF_F16 and stype.
(@ccmp<CCFP_CCFPE:mode><GPF_F16:mode>_rev): Likewise.
gcc/testsuite/
* gcc.target/aarch64/fccmp_1.c: New test.
* gcc.target/aarch64/fccmp_2.c: Likewise.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/config/aarch64/aarch64.cc | 19 ++++++---
gcc/config/aarch64/aarch64.md | 16 ++++----
gcc/testsuite/gcc.target/aarch64/fccmp_1.c | 47 ++++++++++++++++++++++
gcc/testsuite/gcc.target/aarch64/fccmp_2.c | 12 ++++++
4 files changed, 81 insertions(+), 13 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/aarch64/fccmp_1.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/fccmp_2.c
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index d19ca305d82..8e1eb2d7e33 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -29621,6 +29621,17 @@ aarch64_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn
**gen_seq,
icode = CODE_FOR_cmpdi;
break;
+ case E_HFmode:
+ if (!TARGET_FP_F16INST)
+ {
+ end_sequence ();
+ return NULL_RTX;
+ }
+ cmp_mode = HFmode;
+ cc_mode = aarch64_select_cc_mode (code, op0, op1);
+ icode = cc_mode == CCFPEmode ? CODE_FOR_fcmpehf : CODE_FOR_fcmphf;
+ break;
+
case E_SFmode:
cmp_mode = SFmode;
cc_mode = aarch64_select_cc_mode (code, op0, op1);
@@ -29677,6 +29688,7 @@ aarch64_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn
**gen_seq, rtx prev,
/* Exit early for modes that are ot handled to avoid O(n^2) part of
expand_operands. */
op_mode = TYPE_MODE (TREE_TYPE (treeop0));
if (!(op_mode == QImode || op_mode == HImode || op_mode == SImode || op_mode
== DImode
+ || (op_mode == HFmode && TARGET_FP_F16INST)
|| op_mode == SFmode || op_mode == DFmode))
return NULL_RTX;
@@ -29702,13 +29714,10 @@ aarch64_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn
**gen_seq, rtx prev,
cmp_mode = DImode;
break;
+ case E_HFmode:
case E_SFmode:
- cmp_mode = SFmode;
- cc_mode = aarch64_select_cc_mode (cmp_code, op0, op1);
- break;
-
case E_DFmode:
- cmp_mode = DFmode;
+ cmp_mode = op_mode;
cc_mode = aarch64_select_cc_mode (cmp_code, op0, op1);
break;
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index b2185c63819..9da5de8429f 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1134,21 +1134,21 @@
}
)
-(define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>"
+(define_insn "@ccmp<CCFP_CCFPE:mode><GPF_F16:mode>"
[(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
(if_then_else:CCFP_CCFPE
(match_operator 4 "aarch64_comparison_operator"
[(match_operand 0 "cc_register" "")
(const_int 0)])
(compare:CCFP_CCFPE
- (match_operand:GPF 2 "register_operand" "w")
- (match_operand:GPF 3 "register_operand" "w"))
+ (match_operand:GPF_F16 2 "register_operand" "w")
+ (match_operand:GPF_F16 3 "register_operand" "w"))
(unspec:CCFP_CCFPE
[(match_operand 5 "immediate_operand")]
UNSPEC_NZCV)))]
"TARGET_FLOAT"
"fccmp<e>\\t%<s>2, %<s>3, %k5, %m4"
- [(set_attr "type" "fccmp<s>")]
+ [(set_attr "type" "fccmp<stype>")]
)
(define_insn "@ccmp<CC_ONLY:mode><GPI:mode>_rev"
@@ -1171,7 +1171,7 @@
}
)
-(define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>_rev"
+(define_insn "@ccmp<CCFP_CCFPE:mode><GPF_F16:mode>_rev"
[(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
(if_then_else:CCFP_CCFPE
(match_operator 4 "aarch64_comparison_operator"
@@ -1181,11 +1181,11 @@
[(match_operand 5 "immediate_operand")]
UNSPEC_NZCV)
(compare:CCFP_CCFPE
- (match_operand:GPF 2 "register_operand" "w")
- (match_operand:GPF 3 "register_operand" "w"))))]
+ (match_operand:GPF_F16 2 "register_operand" "w")
+ (match_operand:GPF_F16 3 "register_operand" "w"))))]
"TARGET_FLOAT"
"fccmp<e>\\t%<s>2, %<s>3, %k5, %M4"
- [(set_attr "type" "fccmp<s>")]
+ [(set_attr "type" "fccmp<stype>")]
)
;; Expansion of signed mod by a power of 2 using CSNEG.
diff --git a/gcc/testsuite/gcc.target/aarch64/fccmp_1.c
b/gcc/testsuite/gcc.target/aarch64/fccmp_1.c
new file mode 100644
index 00000000000..96d6f717136
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fccmp_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-trapping-math -march=armv8.2-a+fp16" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* FCCMP and FCCMPE have half precision forms when FEAT_FP16 is available.
+ Trapping behaviour is disabled so each conditional comparison is safe. */
+
+/*
+** hf_lt:
+** fcmpe h0, h1
+** fccmpe h2, h3, 0, mi
+** cset w0, mi
+** ret
+*/
+int
+hf_lt (_Float16 a, _Float16 b, _Float16 c, _Float16 d)
+{
+ return (a < b) && (c < d);
+}
+
+/*
+** hf_eq:
+** fcmp h0, h1
+** fccmp h2, h3, 0, eq
+** cset w0, eq
+** ret
+*/
+int
+hf_eq (_Float16 a, _Float16 b, _Float16 c, _Float16 d)
+{
+ return (a == b) && (c == d);
+}
+
+/* Exercise the reverse conditional-compare pattern. */
+
+/*
+** hf_ior:
+** fcmpe h0, h1
+** fccmpe h2, h3, 8, pl
+** cset w0, mi
+** ret
+*/
+int
+hf_ior (_Float16 a, _Float16 b, _Float16 c, _Float16 d)
+{
+ return (a < b) || (c < d);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/fccmp_2.c
b/gcc/testsuite/gcc.target/aarch64/fccmp_2.c
new file mode 100644
index 00000000000..c54a83b2eef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fccmp_2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8.2-a+nofp16" } */
+
+int
+hf_and (_Float16 a, _Float16 b, _Float16 c, _Float16 d)
+{
+ return (a == b) && (c == d);
+}
+
+/* FEAT_FP16 is required for half precision compare instructions. */
+/* { dg-final { scan-assembler-not {\tfcmpe?\th} } } */
+/* { dg-final { scan-assembler-not {\tfccmpe?\th} } } */
--
2.50.1 (Apple Git-155)