Skip to content

Commit 9259c3e

Browse files
Add new interleave and deinterleave builtins (#81689)
Ideally we'd be able to use the llvm interleave2 and deinterleave2 intrinsics instead of adding these, but deinterleave currently isn't available from Swift, and even if you hack that in, the codegen from LLVM is worse than what shufflevector produces for both x86 and arm. So in the medium-term we'll use these builtins, and hope to remove them in favor of [de]interleave2 at some future point.
1 parent bbe1185 commit 9259c3e

File tree

9 files changed

+116
-1
lines changed

9 files changed

+116
-1
lines changed

include/swift/AST/Builtins.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,9 +680,15 @@ BUILTIN_MISC_OPERATION(InsertElement, "insertelement", "n", Special)
680680
/// T must be trivial.
681681
BUILTIN_MISC_OPERATION(Select, "select", "n", Special)
682682

683-
// Shufflevector has type (VecN<T>, VecN<T>, VecM<Int32>) -> VecM<T>
683+
/// Shufflevector has type (VecN<T>, VecN<T>, VecM<Int32>) -> VecM<T>
684684
BUILTIN_MISC_OPERATION(ShuffleVector, "shufflevector", "n", Special)
685685

686+
/// Interleave has type (VecN<T>, VecN<T>) -> (VecN<T>, VecN<T>)
687+
BUILTIN_MISC_OPERATION(Interleave, "interleave", "n", Special)
688+
689+
/// Deinterleave has type (VecN<T>, VecN<T>) -> (VecN<T>, VecN<T>)
690+
BUILTIN_MISC_OPERATION(Deinterleave, "deinterleave", "n", Special)
691+
686692
/// StaticReport has type (Builtin.Int1, Builtin.Int1, Builtin.RawPointer) -> ()
687693
BUILTIN_MISC_OPERATION(StaticReport, "staticReport", "", Special)
688694

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ LANGUAGE_FEATURE(GeneralizedIsSameMetaTypeBuiltin, 465, "Builtin.is_same_metatyp
266266
SUPPRESSIBLE_LANGUAGE_FEATURE(ABIAttributeSE0479, 479, "@abi attribute on functions, initializers, properties, and subscripts")
267267
LANGUAGE_FEATURE(AlwaysInheritActorContext, 472, "@_inheritActorContext(always)")
268268
LANGUAGE_FEATURE(BuiltinSelect, 0, "Builtin.select")
269+
LANGUAGE_FEATURE(BuiltinInterleave, 0, "Builtin.interleave and Builtin.deinterleave")
269270

270271
// Swift 6
271272
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)

lib/AST/Builtins.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,6 +2035,38 @@ static ValueDecl *getShuffleVectorOperation(ASTContext &Context, Identifier Id,
20352035
return getBuiltinFunction(Id, ArgElts, ResultTy);
20362036
}
20372037

2038+
static ValueDecl *getInterleaveOperation(ASTContext &Context, Identifier Id,
2039+
Type FirstTy) {
2040+
// (Vector<N,T>, Vector<N,T>) -> (Vector<N,T>, Vector<N,T>)
2041+
auto VecTy = FirstTy->getAs<BuiltinVectorType>();
2042+
// Require even length because we don't need anything else to support Swift's
2043+
// SIMD types and it saves us from having to define what happens for odd
2044+
// lengths until we actually need to care about them.
2045+
if (!VecTy || VecTy->getNumElements() % 2 != 0)
2046+
return nullptr;
2047+
2048+
Type ArgElts[] = { VecTy, VecTy };
2049+
TupleTypeElt ResultElts[] = { FirstTy, FirstTy };
2050+
Type ResultTy = TupleType::get(ResultElts, Context);
2051+
return getBuiltinFunction(Id, ArgElts, ResultTy);
2052+
}
2053+
2054+
static ValueDecl *getDeinterleaveOperation(ASTContext &Context, Identifier Id,
2055+
Type FirstTy) {
2056+
// (Vector<N,T>, Vector<N,T>) -> (Vector<N,T>, Vector<N,T>)
2057+
auto VecTy = FirstTy->getAs<BuiltinVectorType>();
2058+
// Require even length because we don't need anything else to support Swift's
2059+
// SIMD types and it saves us from having to define what happens for odd
2060+
// lengths until we actually need to care about them.
2061+
if (!VecTy || VecTy->getNumElements() % 2 != 0)
2062+
return nullptr;
2063+
2064+
Type ArgElts[] = { VecTy, VecTy };
2065+
TupleTypeElt ResultElts[] = { FirstTy, FirstTy };
2066+
Type ResultTy = TupleType::get(ResultElts, Context);
2067+
return getBuiltinFunction(Id, ArgElts, ResultTy);
2068+
}
2069+
20382070
static ValueDecl *getStaticReportOperation(ASTContext &Context, Identifier Id) {
20392071
auto BoolTy = BuiltinIntegerType::get(1, Context);
20402072
auto MessageTy = Context.TheRawPointerType;
@@ -3161,6 +3193,14 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
31613193
case BuiltinValueKind::ShuffleVector:
31623194
if (Types.size() != 2) return nullptr;
31633195
return getShuffleVectorOperation(Context, Id, Types[0], Types[1]);
3196+
3197+
case BuiltinValueKind::Interleave:
3198+
if (Types.size() != 1) return nullptr;
3199+
return getInterleaveOperation(Context, Id, Types[0]);
3200+
3201+
case BuiltinValueKind::Deinterleave:
3202+
if (Types.size() != 1) return nullptr;
3203+
return getDeinterleaveOperation(Context, Id, Types[0]);
31643204

31653205
case BuiltinValueKind::StaticReport:
31663206
if (!Types.empty()) return nullptr;

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,7 @@ static bool usesFeatureDefaultIsolationPerFile(Decl *D) {
678678
}
679679

680680
UNINTERESTING_FEATURE(BuiltinSelect)
681+
UNINTERESTING_FEATURE(BuiltinInterleave)
681682

682683
// ----------------------------------------------------------------------------
683684
// MARK: - FeatureSet

lib/IRGen/GenBuiltin.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,47 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
916916
out.add(IGF.Builder.CreateShuffleVector(dict0, dict1, index));
917917
return;
918918
}
919+
920+
if (Builtin.ID == BuiltinValueKind::Interleave) {
921+
using namespace llvm;
922+
923+
auto src0 = args.claimNext();
924+
auto src1 = args.claimNext();
925+
926+
int n = Builtin.Types[0]->getAs<BuiltinVectorType>()->getNumElements();
927+
SmallVector<int> shuffleLo(n);
928+
SmallVector<int> shuffleHi(n);
929+
for (int i=0; i<n/2; ++i) {
930+
shuffleLo[2*i] = i;
931+
shuffleHi[2*i] = n/2 + i;
932+
shuffleLo[2*i+1] = n + i;
933+
shuffleHi[2*i+1] = 3*n/2 + i;
934+
}
935+
936+
out.add(IGF.Builder.CreateShuffleVector(src0, src1, shuffleLo));
937+
out.add(IGF.Builder.CreateShuffleVector(src0, src1, shuffleHi));
938+
return;
939+
}
940+
941+
942+
if (Builtin.ID == BuiltinValueKind::Deinterleave) {
943+
using namespace llvm;
944+
945+
auto src0 = args.claimNext();
946+
auto src1 = args.claimNext();
947+
948+
int n = Builtin.Types[0]->getAs<BuiltinVectorType>()->getNumElements();
949+
SmallVector<int> shuffleEven(n);
950+
SmallVector<int> shuffleOdd(n);
951+
for (int i=0; i<n; ++i) {
952+
shuffleEven[i] = 2*i;
953+
shuffleOdd[i] = 2*i + 1;
954+
}
955+
956+
out.add(IGF.Builder.CreateShuffleVector(src0, src1, shuffleEven));
957+
out.add(IGF.Builder.CreateShuffleVector(src0, src1, shuffleOdd));
958+
return;
959+
}
919960

920961
if (Builtin.ID == BuiltinValueKind::SToSCheckedTrunc ||
921962
Builtin.ID == BuiltinValueKind::UToUCheckedTrunc ||

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,8 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Shl)
889889
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GenericShl)
890890
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Select)
891891
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, ShuffleVector)
892+
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Interleave)
893+
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Deinterleave)
892894
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Sizeof)
893895
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, StaticReport)
894896
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Strideof)

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,8 @@ UNOWNED_OR_NONE_DEPENDING_ON_RESULT(ExtractElement)
680680
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(InsertElement)
681681
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(Select)
682682
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(ShuffleVector)
683+
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(Interleave)
684+
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(Deinterleave)
683685
#undef UNOWNED_OR_NONE_DEPENDING_ON_RESULT
684686

685687
#define OWNED_OR_NONE_DEPENDING_ON_RESULT(ID) \

lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ static bool isBarrier(SILInstruction *inst) {
123123
case BuiltinValueKind::InsertElement:
124124
case BuiltinValueKind::Select:
125125
case BuiltinValueKind::ShuffleVector:
126+
case BuiltinValueKind::Interleave:
127+
case BuiltinValueKind::Deinterleave:
126128
case BuiltinValueKind::StaticReport:
127129
case BuiltinValueKind::AssertConf:
128130
case BuiltinValueKind::StringObjectOr:

test/IRGen/builtins.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,26 @@ func vector_select_test(
204204
return Builtin.select_Vec8xInt1_Vec8xInt32(p, trueValue, falseValue)
205205
}
206206

207+
func interleave_test(
208+
_ evens: Builtin.Vec8xInt16,
209+
_ odds: Builtin.Vec8xInt16
210+
) -> (Builtin.Vec8xInt16, Builtin.Vec8xInt16) {
211+
// CHECK: interleave_test
212+
// CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
213+
// CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
214+
return Builtin.interleave_Vec8xInt16(evens, odds)
215+
}
216+
217+
func deinterleave_test(
218+
_ low: Builtin.Vec8xInt16,
219+
_ high: Builtin.Vec8xInt16
220+
) -> (Builtin.Vec8xInt16, Builtin.Vec8xInt16) {
221+
// CHECK: deinterleave_test
222+
// CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
223+
// CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
224+
return Builtin.deinterleave_Vec8xInt16(low, high)
225+
}
226+
207227
func intrinsic_test(_ i32: inout Builtin.Int32, i16: inout Builtin.Int16,
208228
_ v8i16: Builtin.Vec8xInt16) {
209229
// CHECK: intrinsic_test

0 commit comments

Comments
 (0)