Skip to content

Commit 3aa7b59

Browse files
Implement Builtin.select binding llvm select instruction (#81598)
Not used (yet), but needed to implement SIMD.replacing(with:where:) idiomatically, and probably useful otherwise.
1 parent dfa4bf7 commit 3aa7b59

File tree

9 files changed

+78
-0
lines changed

9 files changed

+78
-0
lines changed

include/swift/AST/Builtins.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,13 @@ BUILTIN_MISC_OPERATION(ExtractElement, "extractelement", "n", Special)
673673
/// InsertElement has type (Vector<N, T>, T, Int32) -> Vector<N, T>.
674674
BUILTIN_MISC_OPERATION(InsertElement, "insertelement", "n", Special)
675675

676+
/// Select has type either
677+
/// (VecN<Int1>, VecN<T>, VecN<T>) -> VecN<T>
678+
/// or
679+
/// (Int1, T, T) -> T
680+
/// T must be trivial.
681+
BUILTIN_MISC_OPERATION(Select, "select", "n", Special)
682+
676683
// Shufflevector has type (VecN<T>, VecN<T>, VecM<Int32>) -> VecM<T>
677684
BUILTIN_MISC_OPERATION(ShuffleVector, "shufflevector", "n", Special)
678685

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ LANGUAGE_FEATURE(ValueGenericsNameLookup, 452, "Value generics appearing as stat
260260
LANGUAGE_FEATURE(GeneralizedIsSameMetaTypeBuiltin, 465, "Builtin.is_same_metatype with support for noncopyable/nonescapable types")
261261
SUPPRESSIBLE_LANGUAGE_FEATURE(ABIAttributeSE0479, 479, "@abi attribute on functions, initializers, properties, and subscripts")
262262
LANGUAGE_FEATURE(AlwaysInheritActorContext, 472, "@_inheritActorContext(always)")
263+
LANGUAGE_FEATURE(BuiltinSelect, 0, "Builtin.select")
263264

264265
// Swift 6
265266
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)

lib/AST/Builtins.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,6 +1994,26 @@ static ValueDecl *getInsertElementOperation(ASTContext &Context, Identifier Id,
19941994
return getBuiltinFunction(Id, ArgElts, VecTy);
19951995
}
19961996

1997+
static ValueDecl *getSelectOperation(ASTContext &Context, Identifier Id,
1998+
Type PredTy, Type ValueTy) {
1999+
// Check for (NxInt1, NxTy, NxTy) -> NxTy
2000+
auto VecPredTy = PredTy->getAs<BuiltinVectorType>();
2001+
if (VecPredTy) {
2002+
// ValueTy must also be vector type with matching element count.
2003+
auto VecValueTy = ValueTy->getAs<BuiltinVectorType>();
2004+
if (!VecValueTy ||
2005+
VecPredTy->getNumElements() != VecValueTy->getNumElements())
2006+
return nullptr;
2007+
} else {
2008+
// Type is (Int1, Ty, Ty) -> Ty
2009+
auto IntTy = PredTy->getAs<BuiltinIntegerType>();
2010+
if (!IntTy || !IntTy->isFixedWidth() || IntTy->getFixedWidth() != 1)
2011+
return nullptr;
2012+
}
2013+
Type ArgElts[] = { PredTy, ValueTy, ValueTy };
2014+
return getBuiltinFunction(Id, ArgElts, ValueTy);
2015+
}
2016+
19972017
static ValueDecl *getShuffleVectorOperation(ASTContext &Context, Identifier Id,
19982018
Type FirstTy, Type SecondTy) {
19992019
// (Vector<N, T>, Vector<N, T>, Vector<M, Int32) -> Vector<M, T>
@@ -3132,6 +3152,10 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
31323152
case BuiltinValueKind::InsertElement:
31333153
if (Types.size() != 3) return nullptr;
31343154
return getInsertElementOperation(Context, Id, Types[0], Types[1], Types[2]);
3155+
3156+
case BuiltinValueKind::Select:
3157+
if (Types.size() != 2) return nullptr;
3158+
return getSelectOperation(Context, Id, Types[0], Types[1]);
31353159

31363160
case BuiltinValueKind::ShuffleVector:
31373161
if (Types.size() != 2) return nullptr;

lib/AST/FeatureSet.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,8 @@ static bool usesFeatureAlwaysInheritActorContext(Decl *decl) {
639639
return false;
640640
}
641641

642+
UNINTERESTING_FEATURE(BuiltinSelect)
643+
642644
// ----------------------------------------------------------------------------
643645
// MARK: - FeatureSet
644646
// ----------------------------------------------------------------------------

lib/IRGen/GenBuiltin.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,16 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
897897
return;
898898
}
899899

900+
if (Builtin.ID == BuiltinValueKind::Select) {
901+
using namespace llvm;
902+
903+
auto pred = args.claimNext();
904+
auto ifTrue = args.claimNext();
905+
auto ifFalse = args.claimNext();
906+
out.add(IGF.Builder.CreateSelect(pred, ifTrue, ifFalse));
907+
return;
908+
}
909+
900910
if (Builtin.ID == BuiltinValueKind::ShuffleVector) {
901911
using namespace llvm;
902912

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,7 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, SToUCheckedTrunc)
887887
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Expect)
888888
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Shl)
889889
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GenericShl)
890+
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Select)
890891
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, ShuffleVector)
891892
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Sizeof)
892893
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, StaticReport)

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,7 @@ UNOWNED_OR_NONE_DEPENDING_ON_RESULT(CmpXChg)
678678
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(AtomicLoad)
679679
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(ExtractElement)
680680
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(InsertElement)
681+
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(Select)
681682
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(ShuffleVector)
682683
#undef UNOWNED_OR_NONE_DEPENDING_ON_RESULT
683684

lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ static bool isBarrier(SILInstruction *inst) {
121121
case BuiltinValueKind::OnFastPath:
122122
case BuiltinValueKind::ExtractElement:
123123
case BuiltinValueKind::InsertElement:
124+
case BuiltinValueKind::Select:
124125
case BuiltinValueKind::ShuffleVector:
125126
case BuiltinValueKind::StaticReport:
126127
case BuiltinValueKind::AssertConf:

test/IRGen/builtins.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,37 @@ func shufflevector_test(_ src: Builtin.FPIEEE32) -> Builtin.Vec4xFPIEEE32 {
173173
)
174174
}
175175

176+
func scalar_select_test(
177+
_ predicate: Builtin.Int1,
178+
_ trueValue: Builtin.Int32,
179+
_ falseValue: Builtin.Int32
180+
) -> Builtin.Int32 {
181+
// CHECK: scalar_select_test
182+
// CHECK: select i1 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}
183+
Builtin.select_Int1_Int32(predicate, trueValue, falseValue)
184+
}
185+
186+
func scalar_select_test_ii(
187+
_ predicate: Builtin.Int1,
188+
_ trueValue: Builtin.Vec4xInt32,
189+
_ falseValue: Builtin.Vec4xInt32
190+
) -> Builtin.Vec4xInt32 {
191+
// CHECK: scalar_select_test_ii
192+
// CHECK: select i1 %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}
193+
Builtin.select_Int1_Vec4xInt32(predicate, trueValue, falseValue)
194+
}
195+
196+
func vector_select_test(
197+
_ predicate: Builtin.Vec8xInt32,
198+
_ trueValue: Builtin.Vec8xInt32,
199+
_ falseValue: Builtin.Vec8xInt32
200+
) -> Builtin.Vec8xInt32 {
201+
// CHECK: vector_select_test
202+
// CHECK: select <8 x i1> %{{[0-9]+}}, <8 x i32> %{{[0-9]+}}, <8 x i32> %{{[0-9]+}}
203+
let p = Builtin.trunc_Vec8xInt32_Vec8xInt1(predicate)
204+
return Builtin.select_Vec8xInt1_Vec8xInt32(p, trueValue, falseValue)
205+
}
206+
176207
func intrinsic_test(_ i32: inout Builtin.Int32, i16: inout Builtin.Int16,
177208
_ v8i16: Builtin.Vec8xInt16) {
178209
// CHECK: intrinsic_test

0 commit comments

Comments
 (0)