Skip to content

Concrete SIMD operations, part 1 #36172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ set(SWIFTLIB_SOURCES

set(SWIFTLIB_GYB_SOURCES
${SWIFTLIB_ESSENTIAL_GYB_SOURCES}
SIMDConcreteOperations.swift.gyb
SIMDVectorTypes.swift.gyb
Tuple.swift.gyb
)
Expand Down
1 change: 1 addition & 0 deletions stdlib/public/core/GroupInfo.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
"FloatingPointTypes.swift",
"FloatingPointRandom.swift"],
"Vector": [
"SIMDConcreteOperations.swift",
"SIMDVector.swift",
"SIMDVectorTypes.swift"]}
],
Expand Down
235 changes: 235 additions & 0 deletions stdlib/public/core/SIMDConcreteOperations.swift.gyb
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
//===--- SIMDConcreteOperations.swift -------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

%{
from __future__ import division
from SwiftIntTypes import all_integer_types
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
storagescalarCounts = [2,4,8,16,32,64]
vectorscalarCounts = storagescalarCounts + [3]
}%

%for int in all_integer_types(word_bits):
% Scalar = int.stdlib_name
% for n in vectorscalarCounts:
% Vector = "SIMD" + str(n) + "<" + Scalar + ">"
% storageN = 4 if n == 3 else n
% s = "s" if int.is_signed else "u"
% Builtin = "Vec" + str(storageN) + "xInt" + str(int.bits)
% if int.is_signed:
extension SIMDMask where Storage == ${Vector} {
@_alwaysEmitIntoClient
internal init(_ _builtin: Builtin.Vec${storageN}xInt1) {
_storage = ${Vector}(Builtin.sext_Vec${storageN}xInt1_${Builtin}(_builtin))
}

@_alwaysEmitIntoClient
internal static var allTrue: Self {
let zero = ${Vector}()
return zero .== zero
}

/// A vector mask that is the boolean negation of the input.
@_alwaysEmitIntoClient
public static prefix func .!(a: Self) -> Self {
a .^ .allTrue
}

/// A vector mask that is the boolean conjunction of the inputs.
@_alwaysEmitIntoClient
public static func .&(a: Self, b: Self) -> Self {
Self(${Vector}(Builtin.and_${Builtin}(
a._storage._storage._value,
b._storage._storage._value
)))
}

/// A vector mask that is the exclusive or of the inputs.
@_alwaysEmitIntoClient
public static func .^(a: Self, b: Self) -> Self {
Self(${Vector}(Builtin.xor_${Builtin}(
a._storage._storage._value,
b._storage._storage._value
)))
}

/// A vector mask that is the boolean disjunction of the inputs.
@_alwaysEmitIntoClient
public static func .|(a: Self, b: Self) -> Self {
Self(${Vector}(Builtin.or_${Builtin}(
a._storage._storage._value,
b._storage._storage._value
)))
}
}

% end
extension SIMD${n} where Scalar == ${Scalar} {
@_alwaysEmitIntoClient
internal init(_ _builtin: Builtin.${Builtin}) {
_storage = ${Scalar}.SIMD${storageN}Storage(_builtin)
}

/// A vector mask with the result of a pointwise equality comparison.
@_alwaysEmitIntoClient
public static func .==(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.cmp_eq_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise inequality comparison.
@_alwaysEmitIntoClient
public static func .!=(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.cmp_ne_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise less-than comparison.
@_alwaysEmitIntoClient
public static func .<(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.cmp_${s}lt_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise less-than-or-equal-to comparison.
@_alwaysEmitIntoClient
public static func .<=(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.cmp_${s}le_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise greater-than comparison.
@_alwaysEmitIntoClient
public static func .>(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.cmp_${s}gt_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise greater-than-or-equal-to comparison.
@_alwaysEmitIntoClient
public static func .>=(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.cmp_${s}ge_${Builtin}(a._storage._value, b._storage._value)
)
}

/// The wrapping sum of two vectors.
@_alwaysEmitIntoClient
public static func &+(a: Self, b: Self) -> Self {
Self(Builtin.add_${Builtin}(a._storage._value, b._storage._value))
}

/// The wrapping difference of two vectors.
@_alwaysEmitIntoClient
public static func &-(a: Self, b: Self) -> Self {
Self(Builtin.sub_${Builtin}(a._storage._value, b._storage._value))
}

/// The pointwise wrapping product of two vectors.
@_alwaysEmitIntoClient
public static func &*(a: Self, b: Self) -> Self {
Self(Builtin.mul_${Builtin}(a._storage._value, b._storage._value))
}

/// Updates the left hand side with the wrapping sum of the two
/// vectors.
@_alwaysEmitIntoClient
public static func &+=(a: inout Self, b: Self) { a = a &+ b }

/// Updates the left hand side with the wrapping difference of the two
/// vectors.
@_alwaysEmitIntoClient
public static func &-=(a: inout Self, b: Self) { a = a &- b }

/// Updates the left hand side with the pointwise wrapping product of two
/// vectors.
@_alwaysEmitIntoClient
public static func &*=(a: inout Self, b: Self) { a = a &* b }
}

% end
%end

%for (Scalar, bits) in [('Float16',16), ('Float',32), ('Double',64)]:
% for n in vectorscalarCounts:
% Vector = "SIMD" + str(n) + "<" + Scalar + ">"
% storageN = 4 if n == 3 else n
% Builtin = "Vec" + str(storageN) + "xFPIEEE" + str(bits)
% if bits == 16:
#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
% end
extension SIMD${n} where Scalar == ${Scalar} {
@_alwaysEmitIntoClient
internal init(_ _builtin: Builtin.${Builtin}) {
_storage = ${Scalar}.SIMD${storageN}Storage(_builtin)
}

/// A vector mask with the result of a pointwise equality comparison.
@_alwaysEmitIntoClient
public static func .==(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.fcmp_oeq_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise inequality comparison.
@_alwaysEmitIntoClient
public static func .!=(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.fcmp_une_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise less-than comparison.
@_alwaysEmitIntoClient
public static func .<(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.fcmp_olt_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise less-than-or-equal-to comparison.
@_alwaysEmitIntoClient
public static func .<=(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.fcmp_ole_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise greater-than comparison.
@_alwaysEmitIntoClient
public static func .>(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.fcmp_ogt_${Builtin}(a._storage._value, b._storage._value)
)
}

/// A vector mask with the result of a pointwise greater-than-or-equal-to comparison.
@_alwaysEmitIntoClient
public static func .>=(a: Self, b: Self) -> SIMDMask<MaskStorage> {
SIMDMask<MaskStorage>(
Builtin.fcmp_oge_${Builtin}(a._storage._value, b._storage._value)
)
}
}
% if bits == 16:
#endif
% end

% end
%end
10 changes: 6 additions & 4 deletions stdlib/public/core/SIMDVector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ extension SIMD {
}
}

/// Returns a vector mask with the result of a pointwise equality comparison.
/// A vector mask with the result of a pointwise equality comparison.
@_transparent
public static func .==(lhs: Self, rhs: Self) -> SIMDMask<MaskStorage> {
var result = SIMDMask<MaskStorage>()
Expand Down Expand Up @@ -822,26 +822,28 @@ extension SIMD where Scalar: FloatingPoint {
return result
}

/// A vector formed by rounding each lane of the source vector to an integral
/// value according to the specified rounding `rule`.
@_transparent
public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
var result = Self()
for i in result.indices { result[i] = self[i].rounded(rule) }
return result
}

/// Returns the least scalar in the vector.
/// The least scalar in the vector.
@_alwaysEmitIntoClient
public func min() -> Scalar {
return indices.reduce(into: self[0]) { $0 = Scalar.minimum($0, self[$1]) }
}

/// Returns the greatest scalar in the vector.
/// The greatest scalar in the vector.
@_alwaysEmitIntoClient
public func max() -> Scalar {
return indices.reduce(into: self[0]) { $0 = Scalar.maximum($0, self[$1]) }
}

/// Returns the sum of the scalars in the vector.
/// The sum of the scalars in the vector.
@_alwaysEmitIntoClient
public func sum() -> Scalar {
// Implementation note: this eventually be defined to lower to either
Expand Down
10 changes: 10 additions & 0 deletions stdlib/public/core/SIMDVectorTypes.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ extension ${Self}: SIMDScalar {
public init() {
_value = Builtin.zeroInitializer()
}

@_alwaysEmitIntoClient
internal init(_ _builtin: Builtin.Vec${n}x${BuiltinName}) {
_value = _builtin
}

public subscript(index: Int) -> ${Self} {
@_transparent
Expand Down Expand Up @@ -283,6 +288,11 @@ extension ${Self} : SIMDScalar {
public init() {
_value = Builtin.zeroInitializer()
}

@_alwaysEmitIntoClient
internal init(_ _builtin: Builtin.Vec${n}xFPIEEE${bits}) {
_value = _builtin
}

public subscript(index: Int) -> ${Self} {
@_transparent
Expand Down
Loading