[builtins] Deduplicate __eqsf2 and __gtsf2 via macro

The only difference between __eqsf2 and __gtsf2 is whether they return
1 or -1 on NaN. Rather than duplicating all the code, use a macro to
define the function twice and use an argument to decide whether to
negate the return value.

Differential Revision: https://reviews.llvm.org/D61919

llvm-svn: 361207
This commit is contained in:
Petr Hosek 2019-05-20 23:34:24 +00:00
parent 1a5cc629de
commit 48140db797
1 changed files with 30 additions and 77 deletions

View File

@ -37,14 +37,13 @@
//===----------------------------------------------------------------------===//
#include "../assembly.h"
.syntax unified
.text
DEFINE_CODE_STATE
@ int __eqsf2(float a, float b)
.macro COMPARESF2_FUNCTION name:req handle_nan:req
@ int \name(float a, float b)
.p2align 2
DEFINE_COMPILERRT_FUNCTION(__eqsf2)
DEFINE_COMPILERRT_FUNCTION(\name)
#if defined(COMPILER_RT_ARMHF_TARGET)
vmov r0, s0
vmov r1, s1
@ -112,9 +111,9 @@ DEFINE_COMPILERRT_FUNCTION(__eqsf2)
// b < 0 ? 1 : -1. Same if a and b have the opposite sign (ignoring Nan).
movs r0, #1
lsrs r1, #31
bne LOCAL_LABEL(CHECK_NAN)
bne LOCAL_LABEL(CHECK_NAN\@)
negs r0, r0
b LOCAL_LABEL(CHECK_NAN)
b LOCAL_LABEL(CHECK_NAN\@)
1:
#else
it lo
@ -130,7 +129,7 @@ DEFINE_COMPILERRT_FUNCTION(__eqsf2)
// Here both have the same sign and absA > absB.
movs r0, #1
lsrs r1, #31
beq LOCAL_LABEL(CHECK_NAN)
beq LOCAL_LABEL(CHECK_NAN\@)
negs r0, r0
1:
#else
@ -151,7 +150,7 @@ DEFINE_COMPILERRT_FUNCTION(__eqsf2)
// Finally, we need to deal with NaNs. If either argument is NaN, replace
// the value in r0 with 1.
#if defined(USE_THUMB_1)
LOCAL_LABEL(CHECK_NAN):
LOCAL_LABEL(CHECK_NAN\@):
movs r6, #0xff
lsls r6, #24
cmp r2, r6
@ -159,17 +158,32 @@ LOCAL_LABEL(CHECK_NAN):
cmp r3, r6
1:
bls 2f
movs r0, #1
\handle_nan
2:
pop {r6, pc}
#else
cmp r2, #0xff000000
ite ls
cmpls r3, #0xff000000
movhi r0, #1
\handle_nan
JMP(lr)
#endif
END_COMPILERRT_FUNCTION(__eqsf2)
END_COMPILERRT_FUNCTION(\name)
.endm
.syntax unified
.text
DEFINE_CODE_STATE
.macro __eqsf2_handle_nan
#if defined(USE_THUMB_1)
movs r0, #1
#else
movhi r0, #1
#endif
.endm
COMPARESF2_FUNCTION __eqsf2, __eqsf2_handle_nan
DEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __eqsf2)
DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __eqsf2)
@ -180,77 +194,16 @@ DEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __eqsf2)
DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpsf2, __lesf2)
#endif
@ int __gtsf2(float a, float b)
.p2align 2
DEFINE_COMPILERRT_FUNCTION(__gtsf2)
// Identical to the preceding except in that we return -1 for NaN values.
// Given that the two paths share so much code, one might be tempted to
// unify them; however, the extra code needed to do so makes the code size
// to performance tradeoff very hard to justify for such small functions.
#if defined(COMPILER_RT_ARMHF_TARGET)
vmov r0, s0
vmov r1, s1
#endif
.macro __gtsf2_handle_nan
#if defined(USE_THUMB_1)
push {r6, lr}
lsls r2, r0, #1
lsls r3, r1, #1
lsrs r6, r3, #1
orrs r6, r2
beq 1f
movs r6, r0
eors r6, r1
1:
bmi 2f
subs r0, r2, r3
2:
bhs 3f
movs r0, #1
lsrs r1, #31
bne LOCAL_LABEL(CHECK_NAN_2)
negs r0, r0
b LOCAL_LABEL(CHECK_NAN_2)
3:
bls 4f
movs r0, #1
lsrs r1, #31
beq LOCAL_LABEL(CHECK_NAN_2)
negs r0, r0
4:
LOCAL_LABEL(CHECK_NAN_2):
movs r6, #0xff
lsls r6, #24
cmp r2, r6
bhi 5f
cmp r3, r6
5:
bls 6f
movs r0, #1
negs r0, r0
6:
pop {r6, pc}
#else
mov r2, r0, lsl #1
mov r3, r1, lsl #1
orrs r12, r2, r3, lsr #1
it ne
eorsne r12, r0, r1
it pl
subspl r0, r2, r3
it lo
mvnlo r0, r1, asr #31
it hi
movhi r0, r1, asr #31
it ne
orrne r0, r0, #1
cmp r2, #0xff000000
ite ls
cmpls r3, #0xff000000
movhi r0, #-1
JMP(lr)
#endif
END_COMPILERRT_FUNCTION(__gtsf2)
.endm
COMPARESF2_FUNCTION __gtsf2, __gtsf2_handle_nan
DEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __gtsf2)