Skip to content

Commit 999885f

Browse files
Use builtins instead of shims in FloatingPointTypes. (#3454)
* Map .round, .squareRoot, .addProduct, and .formRemainder onto builtins instead of shims where possible.
1 parent acb5226 commit 999885f

File tree

4 files changed

+96
-156
lines changed

4 files changed

+96
-156
lines changed

lib/SIL/SILVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3263,7 +3263,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
32633263
assert(F->isAvailableExternally() &&
32643264
"external declaration of internal SILFunction not allowed");
32653265
assert(!hasSharedVisibility(F->getLinkage()) &&
3266-
"external declarations of SILFunctions with shared visibility is not "
3266+
"external declaration of SILFunction with shared visibility is not "
32673267
"allowed");
32683268
// If F is an external declaration, there is nothing further to do,
32693269
// return.

stdlib/public/SwiftShims/LibcShims.h

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -83,48 +83,67 @@ SWIFT_RUNTIME_STDLIB_INTERFACE
8383
__swift_uint32_t
8484
_swift_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound);
8585

86-
// Math library functions
87-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_remainderf(float, float);
88-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_squareRootf(float);
86+
#if defined __APPLE__
87+
static inline float _swift_stdlib_remainderf(float x, float y) {
88+
return __builtin_remainderf(x, y);
89+
}
90+
91+
static inline float _swift_stdlib_sqrtf(float x) {
92+
return __builtin_sqrtf(x);
93+
}
94+
95+
static inline double _swift_stdlib_remainder(double x, double y) {
96+
return __builtin_remainder(x, y);
97+
}
98+
99+
static inline double _swift_stdlib_sqrt(double x) {
100+
return __builtin_sqrt(x);
101+
}
102+
103+
# if defined __i386__ || defined __x86_64__
104+
// We use void* for these because the importer doesn't know how to map Float80
105+
// to long double.
106+
static inline void _swift_stdlib_remainderl(void *x, const void *y) {
107+
long double *ptr = (long double *)x;
108+
*ptr = __builtin_remainderl(*ptr, *(const long double *)y);
109+
}
110+
111+
static inline void _swift_stdlib_sqrtl(void *x) {
112+
long double *ptr = (long double *)x;
113+
*ptr = __builtin_sqrtl(*ptr);
114+
}
115+
# endif // defined __i386__ || defined __x86_64__
116+
#else
117+
// We want the math shims to be static inline for performance reasons, but
118+
// that causes test failures on Linux at present, and depends on a compiler
119+
// feature (__builtin_xxxx) that may not be available on other platforms.
120+
// They are therefore declared as SWIFT_RUNTIME_STDLIB_INTERFACE functions
121+
// on non-Apple platforms for now.
89122
SWIFT_RUNTIME_STDLIB_INTERFACE
90-
float _swift_stdlib_addProductf(float, float, float);
91-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_roundf(float);
92-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_roundevenf(float);
93-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_truncf(float);
94-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_roundawayf(float);
95-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_ceilf(float);
96-
SWIFT_RUNTIME_STDLIB_INTERFACE float _swift_stdlib_floorf(float);
97-
98-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_remainder(double, double);
99-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_squareRoot(double);
123+
float _swift_stdlib_remainderf(float x, float y);
124+
100125
SWIFT_RUNTIME_STDLIB_INTERFACE
101-
double _swift_stdlib_addProduct(double, double, double);
102-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_round(double);
103-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_roundeven(double);
104-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_trunc(double);
105-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_roundaway(double);
106-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_ceil(double);
107-
SWIFT_RUNTIME_STDLIB_INTERFACE double _swift_stdlib_floor(double);
108-
109-
// TODO: Remove horrible workaround when importer does Float80 <-> long double.
110-
#if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
126+
float _swift_stdlib_sqrtf(float x);
127+
111128
SWIFT_RUNTIME_STDLIB_INTERFACE
112-
void _swift_stdlib_remainderl(void *_self, const void *_other);
129+
double _swift_stdlib_remainder(double x, double y);
130+
113131
SWIFT_RUNTIME_STDLIB_INTERFACE
114-
void _swift_stdlib_squareRootl(void *_self);
132+
double _swift_stdlib_sqrt(double x);
133+
134+
# if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
135+
// We use void* for these because the importer doesn't know how to map Float80
136+
// to long double.
115137
SWIFT_RUNTIME_STDLIB_INTERFACE
116-
void _swift_stdlib_addProductl(void *_self, const void *_lhs, const void *_rhs);
117-
SWIFT_RUNTIME_STDLIB_INTERFACE void _swift_stdlib_roundl(void *_self);
118-
SWIFT_RUNTIME_STDLIB_INTERFACE void _swift_stdlib_roundevenl(void *_self);
119-
SWIFT_RUNTIME_STDLIB_INTERFACE void _swift_stdlib_truncl(void *_self);
120-
SWIFT_RUNTIME_STDLIB_INTERFACE void _swift_stdlib_roundawayl(void *_self);
121-
SWIFT_RUNTIME_STDLIB_INTERFACE void _swift_stdlib_ceill(void *_self);
122-
SWIFT_RUNTIME_STDLIB_INTERFACE void _swift_stdlib_floorl(void *_self);
138+
void _swift_stdlib_remainderl(void *x, const void *y);
139+
140+
SWIFT_RUNTIME_STDLIB_INTERFACE
141+
void _swift_stdlib_sqrtl(void *x);
142+
# endif // defined __i386__ || defined __x86_64__
123143
#endif
124144

125145
#ifdef __cplusplus
126146
}} // extern "C", namespace swift
127147
#endif
128148

129149
#endif // SWIFT_STDLIB_SHIMS_LIBCSHIMS_H
130-

stdlib/public/core/FloatingPointTypes.swift.gyb

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -510,37 +510,30 @@ extension ${Self}: BinaryFloatingPoint {
510510

511511
@_transparent
512512
public mutating func round(_ rule: FloatingPointRoundingRule) {
513-
%if bits == 80:
514513
switch rule {
515514
case .toNearestOrAwayFromZero:
516-
_swift_stdlib_roundl(&self)
515+
_value = Builtin.int_round_FPIEEE${bits}(_value)
517516
case .toNearestOrEven:
518-
_swift_stdlib_roundevenl(&self)
517+
// TODO: switch to roundeven( ) or corresponding builtin when
518+
// available; rint assumes default floating-point environment.
519+
// This is pretty OK at present, since there's no Swifty way
520+
// to fuss with the environment, but we should fix it in the
521+
// long term.
522+
_value = Builtin.int_rint_FPIEEE${bits}(_value)
519523
case .towardZero:
520-
_swift_stdlib_truncl(&self)
524+
_value = Builtin.int_trunc_FPIEEE${bits}(_value)
521525
case .awayFromZero:
522-
_swift_stdlib_roundawayl(&self)
523-
case .up:
524-
_swift_stdlib_ceill(&self)
525-
case .down:
526-
_swift_stdlib_floorl(&self)
527-
}
528-
%else:
529-
switch rule {
530-
case .toNearestOrAwayFromZero:
531-
self = _swift_stdlib_round${cFuncSuffix(bits)}(self)
532-
case .toNearestOrEven:
533-
self = _swift_stdlib_roundeven${cFuncSuffix(bits)}(self)
534-
case .towardZero:
535-
self = _swift_stdlib_trunc${cFuncSuffix(bits)}(self)
536-
case .awayFromZero:
537-
self = _swift_stdlib_roundaway${cFuncSuffix(bits)}(self)
526+
if sign == .minus {
527+
_value = Builtin.int_floor_FPIEEE${bits}(_value)
528+
}
529+
else {
530+
_value = Builtin.int_ceil_FPIEEE${bits}(_value)
531+
}
538532
case .up:
539-
self = _swift_stdlib_ceil${cFuncSuffix(bits)}(self)
533+
_value = Builtin.int_ceil_FPIEEE${bits}(_value)
540534
case .down:
541-
self = _swift_stdlib_floor${cFuncSuffix(bits)}(self)
535+
_value = Builtin.int_floor_FPIEEE${bits}(_value)
542536
}
543-
%end
544537
}
545538

546539
@_transparent
@@ -586,21 +579,16 @@ extension ${Self}: BinaryFloatingPoint {
586579
@_transparent
587580
public mutating func formSquareRoot( ) {
588581
%if bits == 80:
589-
_swift_stdlib_squareRootl(&self)
582+
_swift_stdlib_sqrtl(&self)
590583
%else:
591-
self = _swift_stdlib_squareRoot${cFuncSuffix(bits)}(self)
584+
self = _swift_stdlib_sqrt${cFuncSuffix(bits)}(self)
592585
%end
586+
593587
}
594588

595589
@_transparent
596590
public mutating func addProduct(_ lhs: ${Self}, _ rhs: ${Self}) {
597-
%if bits == 80:
598-
var lhs = lhs
599-
var rhs = rhs
600-
_swift_stdlib_addProductl(&self, &lhs, &rhs)
601-
%else:
602-
self = _swift_stdlib_addProduct${cFuncSuffix(bits)}(self, lhs, rhs)
603-
%end
591+
_value = Builtin.int_fma_FPIEEE${bits}(lhs._value, rhs._value, _value)
604592
}
605593

606594
@_transparent

stdlib/public/stubs/LibcShims.cpp

Lines changed: 23 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -125,104 +125,37 @@ swift::_swift_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound) {
125125
return RandomUniform(getGlobalMT19937());
126126
}
127127

128-
float swift::_swift_stdlib_remainderf(float dividend, float divisor) {
129-
return std::remainder(dividend, divisor);
128+
#if !defined __APPLE__
129+
// These functions are static inline on Apple platforms, and therefore
130+
// function bodies are not needed here. They should ideally be made static
131+
// inlines on other platforms as well.
132+
float swift::_swift_stdlib_remainderf(float x, float y) {
133+
return std::remainder(x, y);
130134
}
131135

132-
float swift::_swift_stdlib_squareRootf(float x) { return std::sqrt(x); }
133-
134-
float swift::_swift_stdlib_addProductf(float addend, float lhs, float rhs) {
135-
return std::fma(lhs, rhs, addend);
136-
}
137-
138-
float swift::_swift_stdlib_roundf(float x) { return std::round(x); }
139-
140-
float swift::_swift_stdlib_roundevenf(float x) {
141-
// TODO: switch to roundevenf( ) when available in backing C libraries, or
142-
// open-code here to correctly handle non-default fenv.
143-
return std::rint(x);
144-
}
145-
146-
float swift::_swift_stdlib_truncf(float x) { return std::trunc(x); }
147-
148-
float swift::_swift_stdlib_roundawayf(float x) {
149-
// No corresponding C function, but trivial to fake.
150-
return x < 0 ? std::floor(x) : std::ceil(x);
151-
}
152-
153-
float swift::_swift_stdlib_ceilf(float x) { return std::ceil(x); }
154-
155-
float swift::_swift_stdlib_floorf(float x) { return std::floor(x); }
156-
157-
double swift::_swift_stdlib_remainder(double dividend, double divisor) {
158-
return std::remainder(dividend, divisor);
159-
}
160-
161-
double swift::_swift_stdlib_squareRoot(double x) { return std::sqrt(x); }
162-
163-
double swift::_swift_stdlib_addProduct(double addend, double lhs, double rhs) {
164-
return std::fma(lhs, rhs, addend);
165-
}
166-
167-
double swift::_swift_stdlib_round(double x) { return std::round(x); }
168-
169-
double swift::_swift_stdlib_roundeven(double x) {
170-
// TODO: switch to roundevenf( ) when available in backing C libraries, or
171-
// open-code here to correctly handle non-default fenv.
172-
return std::rint(x);
173-
}
174-
175-
double swift::_swift_stdlib_trunc(double x) { return std::trunc(x); }
176-
177-
double swift::_swift_stdlib_roundaway(double x) {
178-
// No corresponding C function, but trivial to fake.
179-
return x < 0 ? std::floor(x) : std::ceil(x);
180-
}
181-
182-
double swift::_swift_stdlib_ceil(double x) { return std::ceil(x); }
183-
184-
double swift::_swift_stdlib_floor(double x) { return std::floor(x); }
185-
186-
#if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
187-
void swift::_swift_stdlib_remainderl(void *_self, const void *_other) {
188-
*(long double *)_self = std::remainder(*(long double *)_self,
189-
*(const long double *)_other);
190-
}
191-
192-
void swift::_swift_stdlib_squareRootl(void *_self) {
193-
*(long double *)_self = std::sqrt(*(long double *)_self);
194-
}
195-
196-
void
197-
swift::_swift_stdlib_addProductl(void *_self,
198-
const void *_lhs, const void *_rhs) {
199-
*(long double *)_self = std::fma(*(const long double *)_lhs,
200-
*(const long double *)_rhs,
201-
*(long double *)_self);
202-
}
203-
204-
void swift::_swift_stdlib_roundl(void *_self) {
205-
*(long double *)_self = std::round(*(long double *)_self);
206-
}
207-
208-
void swift::_swift_stdlib_roundevenl(void *_self) {
209-
*(long double *)_self = std::rint(*(long double *)_self);
136+
float swift::_swift_stdlib_sqrtf(float x) {
137+
return std::sqrt(x);
210138
}
211139

212-
void swift::_swift_stdlib_truncl(void *_self) {
213-
*(long double *)_self = std::trunc(*(long double *)_self);
140+
double swift::_swift_stdlib_remainder(double x, double y) {
141+
return std::remainder(x, y);
214142
}
215143

216-
void swift::_swift_stdlib_roundawayl(void *_self) {
217-
long double *ptr = (long double *)_self;
218-
*ptr = *ptr < 0 ? std::floor(*ptr) : std::ceil(*ptr);
144+
double swift::_swift_stdlib_sqrt(double x) {
145+
return std::sqrt(x);
219146
}
220147

221-
void swift::_swift_stdlib_ceill(void *_self) {
222-
*(long double *)_self = std::ceil(*(long double *)_self);
148+
# if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
149+
// We use void* for these because the importer doesn't know how to map Float80
150+
// to long double.
151+
void swift::_swift_stdlib_remainderl(void *x, const void *y) {
152+
long double *ptr = (long double *)x;
153+
*ptr = std::remainder(*ptr, *(const long double *)y);
223154
}
224155

225-
void swift::_swift_stdlib_floorl(void *_self) {
226-
*(long double *)_self = std::floor(*(long double *)_self);
156+
void swift::_swift_stdlib_sqrtl(void *x) {
157+
long double *ptr = (long double *)x;
158+
*ptr = std::sqrt(*ptr);
227159
}
228-
#endif // Have Float80
160+
# endif
161+
#endif // !defined __APPLE__

0 commit comments

Comments
 (0)