Skip to content

Commit b8f42d6

Browse files
authored
Merge pull request #26466 from nvzqz/is_concrete_builtin
2 parents 1224e90 + 931ab46 commit b8f42d6

File tree

15 files changed

+263
-1
lines changed

15 files changed

+263
-1
lines changed

include/swift/AST/Builtins.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,14 @@ BUILTIN_MISC_OPERATION(Strideof, "strideof", "n", Special)
418418
/// IsPOD has type T.Type -> Bool
419419
BUILTIN_MISC_OPERATION(IsPOD, "ispod", "n", Special)
420420

421+
/// IsConcrete has type (T.Type) -> Bool
422+
///
423+
/// If the meta type T is concrete, we can always transform this to `true` at
424+
/// any time in SIL. If it's generic, then we lower it to `false` right before
425+
/// IRGen in IRGenPrepare. This allows for the optimizer to specialize this at
426+
/// -O and eliminate conditional code.
427+
BUILTIN_MISC_OPERATION(IsConcrete, "isConcrete", "n", Special)
428+
421429
/// IsBitwiseTakable has type T.Type -> Bool
422430
BUILTIN_MISC_OPERATION(IsBitwiseTakable, "isbitwisetakable", "n", Special)
423431

lib/AST/Builtins.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,13 @@ static ValueDecl *getIsPODOperation(ASTContext &Context, Identifier Id) {
737737
return builder.build(Id);
738738
}
739739

740+
static ValueDecl *getIsConcrete(ASTContext &Context, Identifier Id) {
741+
BuiltinGenericSignatureBuilder builder(Context);
742+
builder.addParameter(makeMetatype(makeGenericParam()));
743+
builder.setResult(makeConcrete(BuiltinIntegerType::get(1,Context)));
744+
return builder.build(Id);
745+
}
746+
740747
static ValueDecl *getIsBitwiseTakable(ASTContext &Context, Identifier Id) {
741748
BuiltinGenericSignatureBuilder builder(Context);
742749
builder.addParameter(makeMetatype(makeGenericParam()));
@@ -1857,6 +1864,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
18571864
case BuiltinValueKind::IsPOD:
18581865
return getIsPODOperation(Context, Id);
18591866

1867+
case BuiltinValueKind::IsConcrete:
1868+
return getIsConcrete(Context, Id);
1869+
18601870
case BuiltinValueKind::IsBitwiseTakable:
18611871
return getIsBitwiseTakable(Context, Id);
18621872

lib/IRGen/GenBuiltin.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,13 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
179179
return;
180180
}
181181

182+
if (Builtin.ID == BuiltinValueKind::IsConcrete) {
183+
(void)args.claimAll();
184+
auto isConcrete = !substitutions.getReplacementTypes()[0]->hasArchetype();
185+
out.add(llvm::ConstantInt::get(IGF.IGM.Int1Ty, isConcrete));
186+
return;
187+
}
188+
182189
if (Builtin.ID == BuiltinValueKind::IsBitwiseTakable) {
183190
(void)args.claimAll();
184191
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,

lib/SIL/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ ANY_OWNERSHIP_BUILTIN(IntToFPWithOverflow)
983983
ANY_OWNERSHIP_BUILTIN(IntToPtr)
984984
ANY_OWNERSHIP_BUILTIN(IsOptionalType)
985985
ANY_OWNERSHIP_BUILTIN(IsPOD)
986+
ANY_OWNERSHIP_BUILTIN(IsConcrete)
986987
ANY_OWNERSHIP_BUILTIN(IsBitwiseTakable)
987988
ANY_OWNERSHIP_BUILTIN(IsSameMetatype)
988989
ANY_OWNERSHIP_BUILTIN(LShr)

lib/SIL/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Any, Sizeof)
448448
CONSTANT_OWNERSHIP_BUILTIN(Any, Strideof)
449449
CONSTANT_OWNERSHIP_BUILTIN(Any, StringObjectOr)
450450
CONSTANT_OWNERSHIP_BUILTIN(Any, IsPOD)
451+
CONSTANT_OWNERSHIP_BUILTIN(Any, IsConcrete)
451452
CONSTANT_OWNERSHIP_BUILTIN(Any, IsBitwiseTakable)
452453
CONSTANT_OWNERSHIP_BUILTIN(Any, IsSameMetatype)
453454
CONSTANT_OWNERSHIP_BUILTIN(Any, Alignof)

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ class SILCombiner :
285285
/// Instruction visitor helpers.
286286
SILInstruction *optimizeBuiltinCanBeObjCClass(BuiltinInst *AI);
287287

288+
// Optimize the "isConcrete" builtin.
289+
SILInstruction *optimizeBuiltinIsConcrete(BuiltinInst *I);
290+
288291
// Optimize the "trunc_N1_M2" builtin. if N1 is a result of "zext_M1_*" and
289292
// the following holds true: N1 > M1 and M2>= M1
290293
SILInstruction *optimizeBuiltinTruncOrBitCast(BuiltinInst *I);

lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ SILInstruction *SILCombiner::optimizeBuiltinCanBeObjCClass(BuiltinInst *BI) {
102102
llvm_unreachable("Unhandled TypeTraitResult in switch.");
103103
}
104104

105+
SILInstruction *SILCombiner::optimizeBuiltinIsConcrete(BuiltinInst *BI) {
106+
if (BI->getOperand(0)->getType().hasArchetype())
107+
return nullptr;
108+
109+
return Builder.createIntegerLiteral(BI->getLoc(), BI->getType(), 1);
110+
}
111+
105112
static unsigned getTypeWidth(SILType Ty) {
106113
if (auto BuiltinIntTy = Ty.getAs<BuiltinIntegerType>()) {
107114
if (BuiltinIntTy->isFixedWidth()) {
@@ -525,6 +532,8 @@ SILInstruction *SILCombiner::optimizeStringObject(BuiltinInst *BI) {
525532
SILInstruction *SILCombiner::visitBuiltinInst(BuiltinInst *I) {
526533
if (I->getBuiltinInfo().ID == BuiltinValueKind::CanBeObjCClass)
527534
return optimizeBuiltinCanBeObjCClass(I);
535+
if (I->getBuiltinInfo().ID == BuiltinValueKind::IsConcrete)
536+
return optimizeBuiltinIsConcrete(I);
528537
if (I->getBuiltinInfo().ID == BuiltinValueKind::TakeArrayFrontToBack ||
529538
I->getBuiltinInfo().ID == BuiltinValueKind::TakeArrayBackToFront ||
530539
I->getBuiltinInfo().ID == BuiltinValueKind::TakeArrayNoAlias ||

lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ static bool isBarrier(SILInstruction *inst) {
109109
case BuiltinValueKind::Sizeof:
110110
case BuiltinValueKind::Strideof:
111111
case BuiltinValueKind::IsPOD:
112+
case BuiltinValueKind::IsConcrete:
112113
case BuiltinValueKind::IsBitwiseTakable:
113114
case BuiltinValueKind::IsSameMetatype:
114115
case BuiltinValueKind::Alignof:

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,18 @@ static SILValue foldFPTrunc(BuiltinInst *BI, const BuiltinInfo &Builtin,
11661166
return B.createFloatLiteral(Loc, BI->getType(), truncVal);
11671167
}
11681168

1169+
static SILValue constantFoldIsConcrete(BuiltinInst *BI) {
1170+
if (BI->getOperand(0)->getType().hasArchetype()) {
1171+
return SILValue();
1172+
}
1173+
SILBuilderWithScope builder(BI);
1174+
auto *inst = builder.createIntegerLiteral(
1175+
BI->getLoc(), SILType::getBuiltinIntegerType(1, builder.getASTContext()),
1176+
true);
1177+
BI->replaceAllUsesWith(inst);
1178+
return inst;
1179+
}
1180+
11691181
static SILValue constantFoldBuiltin(BuiltinInst *BI,
11701182
Optional<bool> &ResultsInError) {
11711183
const IntrinsicInfo &Intrinsic = BI->getIntrinsicInfo();
@@ -1563,7 +1575,8 @@ void ConstantFolder::initializeWorklist(SILFunction &f) {
15631575
continue;
15641576
}
15651577

1566-
if (isApplyOfBuiltin(*inst, BuiltinValueKind::GlobalStringTablePointer)) {
1578+
if (isApplyOfBuiltin(*inst, BuiltinValueKind::GlobalStringTablePointer) ||
1579+
isApplyOfBuiltin(*inst, BuiltinValueKind::IsConcrete)) {
15671580
WorkList.insert(inst);
15681581
continue;
15691582
}
@@ -1781,6 +1794,17 @@ ConstantFolder::processWorkList() {
17811794
continue;
17821795
}
17831796

1797+
if (isApplyOfBuiltin(*I, BuiltinValueKind::IsConcrete)) {
1798+
if (constantFoldIsConcrete(cast<BuiltinInst>(I))) {
1799+
// Here, the bulitin instruction got folded, so clean it up.
1800+
recursivelyDeleteTriviallyDeadInstructions(
1801+
I, /*force*/ true,
1802+
[&](SILInstruction *DeadI) { WorkList.remove(DeadI); });
1803+
InvalidateInstructions = true;
1804+
}
1805+
continue;
1806+
}
1807+
17841808
// Go through all users of the constant and try to fold them.
17851809
FoldedUsers.clear();
17861810
for (auto Result : I->getResults()) {

stdlib/public/core/Builtin.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,19 @@ func _isPOD<T>(_ type: T.Type) -> Bool {
691691
return Bool(Builtin.ispod(type))
692692
}
693693

694+
/// Returns `true` if `type` is known to refer to a concrete type once all
695+
/// optimizations and constant folding has occurred at the call site. Otherwise,
696+
/// this returns `false` if the check has failed.
697+
///
698+
/// Note that there may be cases in which, despite `T` being concrete at some
699+
/// point in the caller chain, this function will return `false`.
700+
@_alwaysEmitIntoClient
701+
@_transparent
702+
public // @testable
703+
func _isConcrete<T>(_ type: T.Type) -> Bool {
704+
return Bool(Builtin.isConcrete(type))
705+
}
706+
694707
/// Returns `true` if type is a bitwise takable. A bitwise takable type can
695708
/// just be moved to a different address in memory.
696709
@_transparent

test/IRGen/builtin_isConcrete.sil

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-frontend -emit-ir -parse-sil %s -module-name Swift -parse-stdlib | %FileCheck %s
2+
3+
import Builtin
4+
5+
struct MyInt {
6+
var value: Builtin.Int32
7+
}
8+
9+
// CHECK-LABEL: define{{( protected| dllexport)?}} swiftcc i1 @isConcrete_true() {{.*}} {
10+
// CHECK-NEXT: entry:
11+
// CHECK-NEXT: ret i1 true
12+
// CHECK-NEXT: }
13+
sil @isConcrete_true : $@convention(thin) (@thin MyInt.Type) -> Builtin.Int1 {
14+
bb0(%0 : $@thin MyInt.Type):
15+
%1 = builtin "isConcrete"(%0 : $@thin MyInt.Type) : $Builtin.Int1
16+
return %1 : $Builtin.Int1
17+
}
18+
19+
// CHECK-LABEL: define{{( protected| dllexport)?}} swiftcc i1 @isConcrete_false(%swift.type* %T) {{.*}} {
20+
// CHECK-NEXT: entry:
21+
// CHECK: ret i1 false
22+
// CHECK-NEXT: }
23+
sil @isConcrete_false : $@convention(thin) <T> (@thin T.Type) -> Builtin.Int1 {
24+
bb0(%0 : $@thin T.Type):
25+
// FIXME: Explicit specialization is required here when it shouldn't be
26+
%1 = builtin "isConcrete"<T>(%0 : $@thin T.Type) : $Builtin.Int1
27+
return %1 : $Builtin.Int1
28+
}

test/SILOptimizer/constant_propagation.sil

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,3 +1024,25 @@ bb0(%0 : $Builtin.Int64):
10241024
%2 = tuple_extract %1 : $(Builtin.Int64, Builtin.Int64), 0
10251025
return %2 : $Builtin.Int64
10261026
}
1027+
1028+
// CHECK-LABEL: sil [canonical] @isConcrete_true : $@convention(thin) (@thin UInt.Type) -> Builtin.Int1 {
1029+
// CHECK: bb0(
1030+
// CHECK-NEXT: [[RESULT:%.*]] = integer_literal $Builtin.Int1, -1
1031+
// CHECK-NEXT: return [[RESULT]]
1032+
// CHECK-NEXT: } // end sil function 'isConcrete_true'
1033+
sil [canonical] @isConcrete_true : $@convention(thin) (@thin UInt.Type) -> Builtin.Int1 {
1034+
bb0(%0 : $@thin UInt.Type):
1035+
%1 = builtin "isConcrete"(%0 : $@thin UInt.Type) : $Builtin.Int1
1036+
return %1 : $Builtin.Int1
1037+
}
1038+
1039+
// CHECK-LABEL: sil [canonical] @isConcrete_false : $@convention(thin) <T> (@thin T.Type) -> Builtin.Int1 {
1040+
// CHECK: bb0(
1041+
// CHECK-NEXT: [[RESULT:%.*]] = builtin "isConcrete"(
1042+
// CHECK-NEXT: return [[RESULT]]
1043+
// CHECK-NEXT: } // end sil function 'isConcrete_false'
1044+
sil [canonical] @isConcrete_false : $@convention(thin) <T> (@thin T.Type) -> Builtin.Int1 {
1045+
bb0(%0 : $@thin T.Type):
1046+
%1 = builtin "isConcrete"(%0 : $@thin T.Type) : $Builtin.Int1
1047+
return %1 : $Builtin.Int1
1048+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// RUN: %target-swift-frontend -module-name constant_propagation_stdlib %s -parse-stdlib -emit-sil -o - | %FileCheck --check-prefix=CHECK-ONONE %s
2+
// RUN: %target-swift-frontend -module-name constant_propagation_stdlib %s -parse-stdlib -emit-sil -o - -O | %FileCheck --check-prefix=CHECK-O %s
3+
4+
public struct MyInt {
5+
var v: Builtin.Int32
6+
}
7+
8+
// CHECK-ONONE-LABEL: sil @$s27constant_propagation_stdlib15isConcrete_trueyBi1_AA5MyIntVF : $@convention(thin) (MyInt) -> Builtin.Int1 {
9+
// CHECK-ONONE: bb0(
10+
// CHECK-ONONE: [[RESULT:%.*]] = integer_literal $Builtin.Int1, -1
11+
// CHECK-ONONE: return [[RESULT]]
12+
// CHECK-ONONE: } // end sil function '$s27constant_propagation_stdlib15isConcrete_trueyBi1_AA5MyIntVF'
13+
// CHECK-O-LABEL: sil @$s27constant_propagation_stdlib15isConcrete_trueyBi1_AA5MyIntVF : $@convention(thin) (MyInt) -> Builtin.Int1 {
14+
// CHECK-O-NEXT: bb0(
15+
// CHECK-O-NEXT: [[RESULT:%.*]] = integer_literal $Builtin.Int1, -1
16+
// CHECK-O-NEXT: return [[RESULT]]
17+
// CHECK-O-NEXT: } // end sil function '$s27constant_propagation_stdlib15isConcrete_trueyBi1_AA5MyIntVF'
18+
public func isConcrete_true(_ x: MyInt) -> Builtin.Int1 {
19+
return Builtin.isConcrete(MyInt.self)
20+
}
21+
22+
// CHECK-ONONE-LABEL: sil @$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlF : $@convention(thin) <T> (@in_guaranteed T) -> Builtin.Int1 {
23+
// CHECK-ONONE: bb0(
24+
// CHECK-ONONE: [[METATYPE:%.*]] = metatype $@thick T.Type
25+
// CHECK-ONONE: [[RESULT:%.*]] = builtin "isConcrete"<T>([[METATYPE]] : $@thick T.Type) : $Builtin.Int1
26+
// CHECK-ONONE: return [[RESULT]]
27+
// CHECK-ONONE: } // end sil function '$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlF'
28+
// CHECK-O-LABEL: sil [signature_optimized_thunk] [always_inline] @$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlF : $@convention(thin) <T> (@in_guaranteed T) -> Builtin.Int1 {
29+
// CHECK-O: bb0(
30+
// CHECK-O: [[GEN_FUNC:%.*]] = function_ref @$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlFTf4d_n : $@convention(thin) <τ_0_0> () -> Builtin.Int1
31+
// CHECK-O: [[RESULT:%.*]] = apply [[GEN_FUNC]]<T>() : $@convention(thin) <τ_0_0> () -> Builtin.Int1
32+
// CHECK-O: return [[RESULT]]
33+
// CHECK-O: } // end sil function '$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlF'
34+
public func isConcrete_false<T>(_ x: T) -> Builtin.Int1 {
35+
return Builtin.isConcrete(T.self)
36+
}
37+
38+
// CHECK-ONONE-LABEL: sil @$s27constant_propagation_stdlib25isConcrete_generic_calleryBi1_xlF : $@convention(thin) <T> (@in_guaranteed T) -> Builtin.Int1 {
39+
// CHECK-ONONE: bb0(
40+
// CHECK-ONONE: [[GEN_FUNC:%.*]] = function_ref @$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Builtin.Int1
41+
// CHECK-ONONE: [[RESULT:%.*]] = apply [[GEN_FUNC]]<T>(%0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Builtin.Int1
42+
// CHECK-ONONE: return [[RESULT]]
43+
// CHECK-ONONE: } // end sil function '$s27constant_propagation_stdlib25isConcrete_generic_calleryBi1_xlF'
44+
// CHECK-O-LABEL: sil @$s27constant_propagation_stdlib25isConcrete_generic_calleryBi1_xlF : $@convention(thin) <T> (@in_guaranteed T) -> Builtin.Int1 {
45+
// CHECK-O: bb0(
46+
// CHECK-O: [[GEN_FUNC:%.*]] = function_ref @$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlFTf4d_n : $@convention(thin) <τ_0_0> () -> Builtin.Int1
47+
// CHECK-O: [[RESULT:%.*]] = apply [[GEN_FUNC]]<T>() : $@convention(thin) <τ_0_0> () -> Builtin.Int1
48+
// CHECK-O: return [[RESULT]]
49+
// CHECK-O: } // end sil function '$s27constant_propagation_stdlib25isConcrete_generic_calleryBi1_xlF'
50+
public func isConcrete_generic_caller<T>(_ x: T) -> Builtin.Int1 {
51+
return isConcrete_false(x)
52+
}
53+
54+
// CHECK-ONONE-LABEL: sil @$s27constant_propagation_stdlib26isConcrete_concrete_calleryBi1_AA5MyIntVF : $@convention(thin) (MyInt) -> Builtin.Int1 {
55+
// CHECK-ONONE: bb0(
56+
// CHECK-ONONE: [[STACK_ARG:%.*]] = alloc_stack $MyInt
57+
// CHECK-ONONE: store %0 to [[STACK_ARG]] : $*MyInt
58+
// CHECK-ONONE: [[GEN_FUNC:%.*]] = function_ref @$s27constant_propagation_stdlib25isConcrete_generic_calleryBi1_xlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Builtin.Int1
59+
// CHECK-ONONE: [[RESULT:%.*]] = apply [[GEN_FUNC]]<MyInt>([[STACK_ARG]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Builtin.Int1
60+
// CHECK-ONONE: dealloc_stack [[STACK_ARG]] : $*MyInt
61+
// CHECK-ONONE: return [[RESULT]]
62+
// CHECK-ONONE: } // end sil function '$s27constant_propagation_stdlib26isConcrete_concrete_calleryBi1_AA5MyIntVF'
63+
// CHECK-O-LABEL: sil @$s27constant_propagation_stdlib26isConcrete_concrete_calleryBi1_AA5MyIntVF : $@convention(thin) (MyInt) -> Builtin.Int1 {
64+
// CHECK-O: bb0(
65+
// CHECK-O: [[RESULT:%.*]] = integer_literal $Builtin.Int1, -1
66+
// CHECK-O: return [[RESULT]]
67+
// CHECK-O: } // end sil function '$s27constant_propagation_stdlib26isConcrete_concrete_calleryBi1_AA5MyIntVF'
68+
public func isConcrete_concrete_caller(_ x: MyInt) -> Builtin.Int1 {
69+
return isConcrete_generic_caller(x)
70+
}
71+
72+
// CHECK-ONONE-LABEL: sil @$s27constant_propagation_stdlib4main1xBi1__Bi1_Bi1_tAA5MyIntV_tF : $@convention(thin) (MyInt) -> (Builtin.Int1, Builtin.Int1, Builtin.Int1) {
73+
// CHECK-ONONE: bb0(
74+
// CHECK-ONONE: [[IS_CONCRETE_TRUE_FUNC:%.*]] = function_ref @$s27constant_propagation_stdlib15isConcrete_trueyBi1_AA5MyIntVF : $@convention(thin) (MyInt) -> Builtin.Int1
75+
// CHECK-ONONE: [[IS_CONCRETE_TRUE:%.*]] = apply [[IS_CONCRETE_TRUE_FUNC]](%0) : $@convention(thin) (MyInt) -> Builtin.Int1
76+
// CHECK-ONONE: [[STACK_ARG:%.*]] = alloc_stack $MyInt
77+
// CHECK-ONONE: store %0 to [[STACK_ARG]] : $*MyInt
78+
// CHECK-ONONE: [[IS_CONCRETE_FALSE_FUNC:%.*]] = function_ref @$s27constant_propagation_stdlib16isConcrete_falseyBi1_xlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Builtin.Int1
79+
// CHECK-ONONE: [[IS_CONCRETE_FALSE:%.*]] = apply [[IS_CONCRETE_FALSE_FUNC]]<MyInt>([[STACK_ARG]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Builtin.Int1
80+
// CHECK-ONONE: dealloc_stack [[STACK_ARG]] : $*MyInt
81+
// CHECK-ONONE: [[IS_CONCRETE_CONCRETE_CALLER_FUNC:%.*]] = function_ref @$s27constant_propagation_stdlib26isConcrete_concrete_calleryBi1_AA5MyIntVF : $@convention(thin) (MyInt) -> Builtin.Int1
82+
// CHECK-ONONE: [[IS_CONCRETE_CONCRETE_CALLER:%.*]] = apply [[IS_CONCRETE_CONCRETE_CALLER_FUNC]](%0) : $@convention(thin) (MyInt) -> Builtin.Int1
83+
// CHECK-ONONE: [[RESULT:%.*]] = tuple ([[IS_CONCRETE_TRUE]] : $Builtin.Int1, [[IS_CONCRETE_FALSE]] : $Builtin.Int1, [[IS_CONCRETE_CONCRETE_CALLER]] : $Builtin.Int1)
84+
// CHECK-ONONE: return [[RESULT]]
85+
// CHECK-ONONE: } // end sil function '$s27constant_propagation_stdlib4main1xBi1__Bi1_Bi1_tAA5MyIntV_tF'
86+
// CHECK-O-LABEL: sil @$s27constant_propagation_stdlib4main1xBi1__Bi1_Bi1_tAA5MyIntV_tF : $@convention(thin) (MyInt) -> (Builtin.Int1, Builtin.Int1, Builtin.Int1) {
87+
// CHECK-O-NEXT: bb0(
88+
// CHECK-O-NEXT: [[VALUE:%.*]] = integer_literal $Builtin.Int1, -1
89+
// CHECK-O-NEXT: [[RESULT:%.*]] = tuple ([[VALUE]] : $Builtin.Int1, [[VALUE]] : $Builtin.Int1, [[VALUE]] : $Builtin.Int1)
90+
// CHECK-O-NEXT: return [[RESULT]]
91+
// CHECK-O-NEXT: } // end sil function '$s27constant_propagation_stdlib4main1xBi1__Bi1_Bi1_tAA5MyIntV_tF'
92+
public func main(x: MyInt) -> (Builtin.Int1, Builtin.Int1, Builtin.Int1) {
93+
return (isConcrete_true(x), isConcrete_false(x), isConcrete_concrete_caller(x))
94+
}

test/SILOptimizer/sil_combine.sil

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ protocol FakeProtocol {
3636
func requirement()
3737
}
3838

39+
struct MyInt {
40+
var value: Builtin.Int32
41+
}
42+
3943
sil [global_init] @global_init_fun : $@convention(thin) () -> Builtin.RawPointer
4044

4145
sil @user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
@@ -3723,3 +3727,26 @@ bb0(%2 : $TestObjCInit):
37233727
%19 = enum $Optional<TestObjCInit>, #Optional.some!enumelt.1, %14 : $TestObjCInit
37243728
return %19 : $Optional<TestObjCInit>
37253729
}
3730+
3731+
// CHECK-LABEL: sil @isConcrete_true : $@convention(thin) (@thin MyInt.Type) -> Builtin.Int1 {
3732+
// CHECK: bb0(%0 : $@thin MyInt.Type):
3733+
// CHECK: [[RESULT:%.*]] = integer_literal $Builtin.Int1, -1
3734+
// CHECK: return [[RESULT]]
3735+
// CHECK: } // end sil function 'isConcrete_true'
3736+
sil @isConcrete_true : $@convention(thin) (@thin MyInt.Type) -> Builtin.Int1 {
3737+
bb0(%0 : $@thin MyInt.Type):
3738+
%1 = builtin "isConcrete"(%0 : $@thin MyInt.Type) : $Builtin.Int1
3739+
return %1 : $Builtin.Int1
3740+
}
3741+
3742+
// CHECK-LABEL: sil @isConcrete_false : $@convention(thin) <T> (@thin T.Type) -> Builtin.Int1 {
3743+
// CHECK: bb0(%0 : $@thin T.Type):
3744+
// CHECK: [[RESULT:%.*]] = builtin "isConcrete"<T>(%0 : $@thin T.Type) : $Builtin.Int1
3745+
// CHECK: return [[RESULT]]
3746+
// CHECK: } // end sil function 'isConcrete_false'
3747+
sil @isConcrete_false : $@convention(thin) <T> (@thin T.Type) -> Builtin.Int1 {
3748+
bb0(%0 : $@thin T.Type):
3749+
// FIXME: Explicit specialization is required here when it shouldn't be
3750+
%1 = builtin "isConcrete"<T>(%0 : $@thin T.Type) : $Builtin.Int1
3751+
return %1 : $Builtin.Int1
3752+
}

test/stdlib/Builtins.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,4 +293,18 @@ tests.test("_isOptional") {
293293
expectFalse(_isOptional(P.self))
294294
}
295295

296+
tests.test("_isConcrete") {
297+
@_transparent
298+
func isConcrete_true<T>(_ type: T.Type) -> Bool {
299+
return _isConcrete(type)
300+
}
301+
@inline(never)
302+
func isConcrete_false<T>(_ type: T.Type) -> Bool {
303+
return _isConcrete(type)
304+
}
305+
expectTrue(_isConcrete(Int.self))
306+
expectTrue(isConcrete_true(Int.self))
307+
expectFalse(isConcrete_false(Int.self))
308+
}
309+
296310
runAllTests()

0 commit comments

Comments
 (0)