mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
WIP to add more overloads to optimize SIMD codegen on concrete types. Here we do: - init(repeating:) - init(lowHalf:highHalf:) These are always inlined, even in debug, since LLVM knows how to lower them to one or two instructions on the targets that we care about.
145 lines
4.9 KiB
Swift
145 lines
4.9 KiB
Swift
//===--- SIMDIntegerConcreteOperations.swift ------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2021-2025 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 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)
|
|
% MaskExt = "Builtin.sext_Vec" + str(storageN) + "xInt1_" + Builtin
|
|
extension SIMD${n} where Scalar == ${Scalar} {
|
|
@_alwaysEmitIntoClient @_transparent
|
|
internal init(_ _builtin: Builtin.${Builtin}) {
|
|
_storage = ${Scalar}.SIMD${storageN}Storage(_builtin)
|
|
}
|
|
|
|
@_alwaysEmitIntoClient @_transparent
|
|
public init(repeating scalar: ${Scalar}) {
|
|
let asVector = Builtin.insertelement_${Builtin}_Int${int.bits}_Int32(
|
|
Builtin.zeroInitializer(), scalar._value, Builtin.zeroInitializer()
|
|
)
|
|
let repeated = Builtin.shufflevector_${Builtin}_Vec${storageN}xInt32(
|
|
asVector, Builtin.zeroInitializer(), Builtin.zeroInitializer()
|
|
)
|
|
% if n != 3:
|
|
self.init(repeated)
|
|
% else:
|
|
self.init(Builtin.insertelement_${Builtin}_Int${int.bits}_Int32(
|
|
repeated, Builtin.zeroInitializer(), Int32(3)._value
|
|
))
|
|
% end
|
|
}
|
|
|
|
% if n >= 4:
|
|
@_alwaysEmitIntoClient @_transparent
|
|
public init(
|
|
lowHalf: SIMD${n//2}<${Scalar}>,
|
|
highHalf: SIMD${n//2}<${Scalar}>
|
|
) {
|
|
self = unsafe unsafeBitCast((lowHalf, highHalf), to: Self.self)
|
|
}
|
|
|
|
% end
|
|
/// A vector mask with the result of a pointwise equality comparison.
|
|
@_alwaysEmitIntoClient
|
|
public static func .==(a: Self, b: Self) -> SIMDMask<MaskStorage> {
|
|
SIMDMask<MaskStorage>(${MaskExt}(
|
|
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>(${MaskExt}(
|
|
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>(${MaskExt}(
|
|
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>(${MaskExt}(
|
|
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>(${MaskExt}(
|
|
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>(${MaskExt}(
|
|
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
|