Merge pull request #8430 from palimondo/benchmark-conformance-constraint-sources
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 51962f3..8d3995b 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2316,8 +2316,10 @@
}
Type AbstractTypeParamDecl::getSuperclass() const {
- auto *dc = getDeclContext();
- auto contextTy = dc->mapTypeIntoContext(getDeclaredInterfaceType());
+ auto *genericEnv = getDeclContext()->getGenericEnvironmentOfContext();
+ assert(genericEnv != nullptr && "Too much circularity");
+
+ auto contextTy = genericEnv->mapTypeIntoContext(getDeclaredInterfaceType());
if (auto *archetype = contextTy->getAs<ArchetypeType>())
return archetype->getSuperclass();
@@ -2327,8 +2329,10 @@
ArrayRef<ProtocolDecl *>
AbstractTypeParamDecl::getConformingProtocols() const {
- auto *dc = getDeclContext();
- auto contextTy = dc->mapTypeIntoContext(getDeclaredInterfaceType());
+ auto *genericEnv = getDeclContext()->getGenericEnvironmentOfContext();
+ assert(genericEnv != nullptr && "Too much circularity");
+
+ auto contextTy = genericEnv->mapTypeIntoContext(getDeclaredInterfaceType());
if (auto *archetype = contextTy->getAs<ArchetypeType>())
return archetype->getConformsTo();
diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp
index 251b236..602ec48 100644
--- a/lib/AST/SubstitutionMap.cpp
+++ b/lib/AST/SubstitutionMap.cpp
@@ -135,9 +135,16 @@
if (protoAssocType) {
if (conformance.isAbstract()) {
- for (auto assocProto : protoAssocType->getConformingProtocols()) {
- if (auto found = fn(ProtocolConformanceRef(assocProto)))
- return found;
+ // Narrow fix since this whole code path is going away soon
+ // (if you find this code still here a year from now, I will be
+ // very ashamed).
+ //
+ // FIXME: Should always have a valid generic environment.
+ if (protoAssocType->getProtocol()->getGenericEnvironment()) {
+ for (auto assocProto : protoAssocType->getConformingProtocols()) {
+ if (auto found = fn(ProtocolConformanceRef(assocProto)))
+ return found;
+ }
}
} else {
auto sub = conformance.getConcrete()->getTypeWitnessSubstAndDecl(
diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
index a1b9089..7817786 100644
--- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
+++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
@@ -19,7 +19,6 @@
#include "swift/SIL/SILCloner.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/Local.h"
-#include "swift/SILOptimizer/Utils/StackNesting.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
@@ -396,7 +395,8 @@
/// rewriteAllocBoxAsAllocStack - Replace uses of the alloc_box with a
/// new alloc_stack, but do not delete the alloc_box yet.
-static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
+static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI,
+ llvm::SmallVectorImpl<TermInst *> &Returns) {
DEBUG(llvm::dbgs() << "*** Promoting alloc_box to stack: " << *ABI);
llvm::SmallVector<SILInstruction*, 4> FinalReleases;
@@ -405,7 +405,8 @@
// Promote this alloc_box to an alloc_stack. Insert the alloc_stack
// at the beginning of the function.
- SILBuilder BuildAlloc(ABI);
+ auto &Entry = ABI->getFunction()->front();
+ SILBuilder BuildAlloc(&Entry, Entry.begin());
BuildAlloc.setCurrentDebugScope(ABI->getDebugScope());
assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
&& "rewriting multi-field box not implemented");
@@ -439,18 +440,25 @@
.getTypeLowering(ABI->getBoxType()->getFieldType(ABI->getModule(), 0));
auto Loc = CleanupLocation::get(ABI->getLoc());
- for (auto LastRelease : FinalReleases) {
- SILBuilderWithScope Builder(LastRelease);
- if (!isa<DeallocBoxInst>(LastRelease)&& !Lowering.isTrivial()) {
- // For non-trivial types, insert destroys for each final release-like
- // instruction we found that isn't an explicit dealloc_box.
- Builder.emitDestroyAddrAndFold(Loc, PointerResult);
+ // For non-trivial types, insert destroys for each final release-like
+ // instruction we found that isn't an explicit dealloc_box.
+ if (!Lowering.isTrivial()) {
+ for (auto LastRelease : FinalReleases) {
+ if (isa<DeallocBoxInst>(LastRelease))
+ continue;
+
+ SILBuilderWithScope BuildDestroy(LastRelease);
+ BuildDestroy.emitDestroyAddrAndFold(Loc, PointerResult);
}
- Builder.createDeallocStack(Loc, ASI);
}
- // Remove any retain and release instructions. Since all uses of project_box
- // are gone, this only walks through uses of the box itself (the retain count
+ for (auto Return : Returns) {
+ SILBuilderWithScope BuildDealloc(Return);
+ BuildDealloc.createDeallocStack(Loc, ASI);
+ }
+
+ // Remove any retain and release instructions. Since all uses of result #1
+ // are gone, this only walks through uses of result #0 (the retain count
// pointer).
while (!ABI->use_empty()) {
auto *User = (*ABI->use_begin())->getUser();
@@ -817,6 +825,7 @@
static unsigned
rewritePromotedBoxes(llvm::SmallVectorImpl<AllocBoxInst *> &Promoted,
llvm::SmallVectorImpl<Operand *> &PromotedOperands,
+ llvm::SmallVectorImpl<TermInst *> &Returns,
bool &CFGChanged) {
// First we'll rewrite any partial applies that we can to remove the
// box container pointer from the operands.
@@ -826,7 +835,7 @@
auto rend = Promoted.rend();
for (auto I = Promoted.rbegin(); I != rend; ++I) {
auto *ABI = *I;
- if (rewriteAllocBoxAsAllocStack(ABI)) {
+ if (rewriteAllocBoxAsAllocStack(ABI, Returns)) {
++Count;
ABI->eraseFromParent();
}
@@ -840,8 +849,13 @@
void run() override {
llvm::SmallVector<AllocBoxInst *, 8> Promotable;
llvm::SmallVector<Operand *, 8> PromotedOperands;
+ llvm::SmallVector<TermInst *, 8> Returns;
for (auto &BB : *getFunction()) {
+ auto *Term = BB.getTerminator();
+ if (Term->isFunctionExiting())
+ Returns.push_back(Term);
+
for (auto &I : BB)
if (auto *ABI = dyn_cast<AllocBoxInst>(&I))
if (canPromoteAllocBox(ABI, PromotedOperands))
@@ -850,14 +864,9 @@
if (!Promotable.empty()) {
bool CFGChanged = false;
- auto Count = rewritePromotedBoxes(Promotable, PromotedOperands,
+ auto Count = rewritePromotedBoxes(Promotable, PromotedOperands, Returns,
CFGChanged);
NumStackPromoted += Count;
- if (Count) {
- StackNesting SN;
- if (SN.correctStackNesting(getFunction()) == StackNesting::Changes::CFG)
- CFGChanged = true;
- }
invalidateAnalysis(CFGChanged ?
SILAnalysis::InvalidationKind::FunctionBody :
diff --git a/test/DebugInfo/ProtocolContainer.swift b/test/DebugInfo/ProtocolContainer.swift
index 8a8261d..c591db4 100644
--- a/test/DebugInfo/ProtocolContainer.swift
+++ b/test/DebugInfo/ProtocolContainer.swift
@@ -13,7 +13,7 @@
}
// CHECK: define hidden {{.*}}void @_T017ProtocolContainer3foo{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: entry:
-// CHECK: %[[X:.*]] = alloca %T17ProtocolContainer9AProtocolP, align {{(4|8)}}
+// CHECK-NEXT: %[[X:.*]] = alloca %T17ProtocolContainer9AProtocolP, align {{(4|8)}}
// CHECK: call void @llvm.dbg.declare(metadata %T17ProtocolContainer9AProtocolP* %[[X]], metadata ![[XMD:.*]], metadata !{{[0-9]+}})
// CHECK-NOT: !DILocalVariable({{.*}} name: "x"
// CHECK-NOT: !DILocalVariable({{.*}} name: "x"
diff --git a/test/DebugInfo/letstring.swift b/test/DebugInfo/letstring.swift
index bd07910..d5b2f0f 100644
--- a/test/DebugInfo/letstring.swift
+++ b/test/DebugInfo/letstring.swift
@@ -7,16 +7,15 @@
// CHECK: define hidden {{.*}}i1 {{.*}}11AppDelegateC1f
func f() -> Bool {
// Test for -O0 shadow copies.
- // CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[SELF:.*]], metadata !{{[0-9]+}})
- // CHECK-NOT: call void @llvm.dbg.value
- // CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[A:.*]], metadata !{{[0-9]+}})
- let a = "let"
- // CHECK-NOT: call void @llvm.dbg.value
// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[B:.*]], metadata !{{[0-9]+}})
- // CHECK-NOT: call void @llvm.dbg.value
- // CHECK: ret
+ // CHECK-NOT: call void @llvm.dbg.value({{.*}}, metadata ![[B]], metadata !{{[0-9]+}})
+ // CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[SELF:.*]], metadata !{{[0-9]+}})
+ let a = "let"
+ // CHECK-NOT: call void @llvm.dbg.value({{.*}}, metadata ![[SELF]], metadata !{{[0-9]+}})
+ // CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[A:.*]], metadata !{{[0-9]+}})
+ // CHECK-NOT: call void @llvm.dbg.value({{.*}}, metadata ![[A]], metadata !{{[0-9]+}})
+ // CHECK-DAG: ![[A]] = !DILocalVariable(name: "a",{{.*}} line: [[@LINE-4]],
// CHECK-DAG: ![[SELF]] = !DILocalVariable(name: "self", arg: 1{{.*}} line: [[@LINE-10]],
- // CHECK-DAG: ![[A]] = !DILocalVariable(name: "a",{{.*}} line: [[@LINE-6]],
// CHECK-DAG: ![[B]] = !DILocalVariable(name: "b",{{.*}} line: [[@LINE+1]],
var b = "var"
self.window = UIWindow()
@@ -33,7 +32,7 @@
// DWARF-CHECK: DW_AT_name {{.*}} "self"
//
// DWARF-CHECK: DW_TAG_variable
-// DWARF-CHECK: DW_AT_name {{.*}} "a"
+// DWARF-CHECK: DW_AT_name {{.*}} "b"
//
// DWARF-CHECK: DW_TAG_variable
-// DWARF-CHECK: DW_AT_name {{.*}} "b"
+// DWARF-CHECK: DW_AT_name {{.*}} "a"
diff --git a/test/DebugInfo/linetable-cleanups.swift b/test/DebugInfo/linetable-cleanups.swift
index 9183355..caa9b8a 100644
--- a/test/DebugInfo/linetable-cleanups.swift
+++ b/test/DebugInfo/linetable-cleanups.swift
@@ -1,8 +1,5 @@
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s
-// TODO: check why this is failing on linux
-// REQUIRES: OS=macosx
-
func markUsed<T>(_ t: T) {}
class Person {
@@ -24,10 +21,12 @@
// CHECK: call void {{.*[rR]}}elease{{.*}} {{#[0-9]+}}, !dbg ![[LOOPHEADER_LOC]]
// CHECK: call {{.*}}void @_T04main8markUsedyxlF
// The cleanups should share the line number with the ret stmt.
-// CHECK: call void @swift_bridgeObjectRelease({{.*}}) {{#[0-9]+}}, !dbg ![[CLEANUPS:.*]]
+// CHECK: call void {{.*[rR]}}elease{{.*}} {{#[0-9]+}}, !dbg ![[CLEANUPS:.*]]
// CHECK-NEXT: !dbg ![[CLEANUPS]]
+// CHECK-NEXT: bitcast
// CHECK-NEXT: llvm.lifetime.end
// CHECK-NEXT: bitcast
+// CHECK-NEXT: llvm.lifetime.end
// CHECK-NEXT: bitcast
// CHECK-NEXT: llvm.lifetime.end
// CHECK-NEXT: ret void, !dbg ![[CLEANUPS]]
diff --git a/test/DebugInfo/linetable.swift b/test/DebugInfo/linetable.swift
index f9ba1c2..33b5201 100644
--- a/test/DebugInfo/linetable.swift
+++ b/test/DebugInfo/linetable.swift
@@ -34,9 +34,9 @@
var result = my_class.do_something(x)
markUsed(result)
// CHECK: call {{.*}} @swift_rt_swift_release {{.*}}
-// CHECK: bitcast
-// CHECK: llvm.lifetime.end
// CHECK: call {{.*}} @swift_rt_swift_release {{.*}}, !dbg ![[CLOSURE_END:.*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: llvm.lifetime.end
// CHECK-NEXT: ret void, !dbg ![[CLOSURE_END]]
// CHECK: ![[CLOSURE_END]] = !DILocation(line: [[@LINE+1]],
}
diff --git a/test/DebugInfo/protocolarg.swift b/test/DebugInfo/protocolarg.swift
index c7ed868..80ea033 100644
--- a/test/DebugInfo/protocolarg.swift
+++ b/test/DebugInfo/protocolarg.swift
@@ -8,21 +8,21 @@
}
// CHECK: define {{.*}}@_T011protocolarg16printSomeNumbersyAA12IGiveOutInts_pF
-// CHECK: @llvm.dbg.declare(metadata %T11protocolarg12IGiveOutIntsP** %
-// CHECK-SAME: metadata ![[ARG:.*]], metadata ![[DEREF:.*]])
// CHECK: @llvm.dbg.declare(metadata %T11protocolarg12IGiveOutIntsP* %
// CHECK-SAME: metadata ![[VAR:.*]], metadata ![[EMPTY:.*]])
+// CHECK: @llvm.dbg.declare(metadata %T11protocolarg12IGiveOutIntsP** %
+// CHECK-SAME: metadata ![[ARG:.*]], metadata ![[DEREF:.*]])
// CHECK: ![[EMPTY]] = !DIExpression()
public func printSomeNumbers(_ gen: IGiveOutInts) {
var gen = gen
+ // CHECK: ![[VAR]] = !DILocalVariable(name: "gen", {{.*}} line: [[@LINE-1]]
// FIXME: Should be DW_TAG_interface_type
+ // CHECK: ![[PT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "IGiveOutInts"
// CHECK: ![[ARG]] = !DILocalVariable(name: "gen", arg: 1,
- // CHECK-SAME: line: [[@LINE-4]], type: ![[PT:[0-9]+]]
- // CHECK: ![[PT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "IGiveOutInts"
+ // CHECK-SAME: line: [[@LINE-6]], type: ![[PT]]
// CHECK: ![[DEREF]] = !DIExpression(DW_OP_deref)
- // CHECK: ![[VAR]] = !DILocalVariable(name: "gen", {{.*}} line: [[@LINE-6]]
markUsed(gen.callMe())
use(&gen)
}
diff --git a/test/IRGen/dynamic_lookup.sil b/test/IRGen/dynamic_lookup.sil
index bcfa4d8..3390828 100644
--- a/test/IRGen/dynamic_lookup.sil
+++ b/test/IRGen/dynamic_lookup.sil
@@ -76,8 +76,6 @@
br bb3
bb3:
- strong_release %1 : $<τ_0_0> { var τ_0_0 } <AnyObject>
- strong_release %3 : $<τ_0_0> { var τ_0_0 } <Optional<() -> ()>>
%43 = tuple ()
return %43 : $()
}
@@ -121,7 +119,6 @@
br bb3
bb3:
- strong_release %1 : $<τ_0_0> { var τ_0_0 } <AnyObject>
%43 = tuple ()
return %43 : $()
}
@@ -156,8 +153,6 @@
br bb3
bb3:
- strong_release %3 : $<τ_0_0> { var τ_0_0 } <Int>
- strong_release %2 : $<τ_0_0> { var τ_0_0 } <AnyObject>
%30 = tuple ()
return %30 : $()
}
diff --git a/test/SILOptimizer/allocbox_to_stack.sil b/test/SILOptimizer/allocbox_to_stack.sil
index 385dc0f..1a72426 100644
--- a/test/SILOptimizer/allocbox_to_stack.sil
+++ b/test/SILOptimizer/allocbox_to_stack.sil
@@ -243,8 +243,8 @@
strong_release %1 : ${ var SomeUnion }
%10 = tuple ()
return %10 : $()
-// CHECK: dealloc_stack [[UNION]]
// CHECK: [[T0:%.*]] = tuple ()
+// CHECK: dealloc_stack [[UNION]]
// CHECK-NEXT: return [[T0]] : $()
}
@@ -276,27 +276,24 @@
//
// CHECK-LABEL: sil @box_reachable_from_release_test
sil @box_reachable_from_release_test : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: alloc_stack
bb0:
br bb1
-// CHECK: bb1:
-// CHECK-NEXT: alloc_stack
bb1:
%1 = alloc_box ${ var Bool }
cond_br undef, bb2, bb3
-// CHECK: bb2:
-// CHECK-NEXT: dealloc_stack
bb2:
strong_release %1 : ${ var Bool }
br bb1
-// CHECK: bb3:
-// CHECK-NEXT: dealloc_stack
bb3:
strong_release %1 : ${ var Bool }
%2 = tuple ()
-// CHECK: return
+// CHECK: dealloc_stack
+// CHECK-NEXT: return
return %2 : $()
}
@@ -337,19 +334,18 @@
strong_release %2 : ${ var SomeClass }
// CHECK: destroy_addr [[MUI]]
- // CHECK-NEXT: dealloc_stack [[STACK]]
br bb2
// CHECK: bb2
bb2:
%17 = tuple ()
- // CHECK: return
+ // CHECK: dealloc_stack [[STACK]]
+ // CHECK-NEXT: return
return %17 : $()
bb3:
strong_release %2 : ${ var SomeClass }
// CHECK: destroy_addr [[MUI]]
- // CHECK-NEXT: dealloc_stack [[STACK]]
br bb2
}
@@ -490,13 +486,13 @@
sil @callWithAutoclosure : $@convention(thin) <T where T : P> (@in T) -> () {
// CHECK: bb0
bb0(%0 : $*T):
+ // CHECK: [[STACK:%[0-9a-zA-Z_]+]] = alloc_stack $T
// CHECK: debug_value_addr
debug_value_addr %0 : $*T
// CHECK: function_ref @mightApply
%2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
%3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
// CHECK-NOT: alloc_box
- // CHECK: [[STACK:%[0-9a-zA-Z_]+]] = alloc_stack $T
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>
%4a = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
// CHECK: copy_addr %0 to [initialization] [[STACK]] : $*T
@@ -506,10 +502,10 @@
%6 = partial_apply %3<T>(%4) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
%7 = apply %2<T>(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
// CHECK: destroy_addr [[STACK]] : $*T
- // CHECK: dealloc_stack [[STACK]] : $*T
destroy_addr %0 : $*T
%9 = tuple ()
- // CHECK: return
+ // CHECK: dealloc_stack [[STACK]] : $*T
+ // CHECK: return
return %9 : $()
}
@@ -749,253 +745,3 @@
strong_release %2 : ${ var ThrowDerivedClass }
throw %25 : $Error
}
-
-// CHECK-LABEL: sil @deal_with_wrong_nesting
-// CHECK: bb0(%0 : $Int):
-// CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
-// CHECK: bb1:
-// CHECK-NEXT: dealloc_stack [[BOX]]
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK: bb2:
-// CHECK: store
-// CHECK: [[STACK2:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: dealloc_stack [[STACK2]]
-// CHECK-NEXT: dealloc_stack [[BOX]]
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK: bb3:
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-sil @deal_with_wrong_nesting : $(Int) -> () {
-bb0(%0 : $Int):
- %as1 = alloc_stack $Bool
- %1 = alloc_box ${ var Int }
- cond_br undef, bb1, bb2
-
-bb1:
- strong_release %1 : ${ var Int }
- dealloc_stack %as1 : $*Bool
- br bb3
-
-bb2:
- %1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to %1a : $*Int
- dealloc_stack %as1 : $*Bool
- %3 = load %1a : $*Int
- %as2 = alloc_stack $Bool
- strong_release %1 : ${ var Int }
- dealloc_stack %as2 : $*Bool
- br bb3
-
-bb3:
- %r = tuple ()
- %5 = return %r : $()
-}
-
-// CHECK-LABEL: sil @wrong_nesting_with_alloc_ref
-// CHECK: bb0(%0 : $Int):
-// CHECK-NEXT: [[REF:%[0-9]+]] = alloc_ref [stack] $SomeClass
-// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
-// CHECK: store
-// CHECK: dealloc_stack [[BOX]]
-// CHECK-NEXT: dealloc_ref [stack] [[REF]]
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-sil @wrong_nesting_with_alloc_ref : $(Int) -> () {
-bb0(%0 : $Int):
- %as1 = alloc_ref [stack] $SomeClass
- %1 = alloc_box ${ var Int }
- %1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to %1a : $*Int
- dealloc_ref [stack] %as1 : $SomeClass
- %3 = load %1a : $*Int
- strong_release %1 : ${ var Int }
- %r = tuple ()
- %5 = return %r : $()
-}
-
-// CHECK-LABEL: sil @nesting_and_unreachable1
-// CHECK: bb0(%0 : $Int):
-// CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
-// CHECK: bb1:
-// CHECK-NEXT: [[STACK2:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: dealloc_stack [[STACK2]]
-// CHECK-NEXT: unreachable
-// CHECK: bb2:
-// CHECK: store
-// CHECK: dealloc_stack [[BOX]]
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-sil @nesting_and_unreachable1 : $(Int) -> () {
-bb0(%0 : $Int):
- %as1 = alloc_stack $Bool
- %1 = alloc_box ${ var Int }
- %1a = project_box %1 : ${ var Int }, 0
- cond_br undef, bb1, bb2
-
-bb1:
- %as2 = alloc_stack $Bool
- dealloc_stack %as2 : $*Bool
- unreachable
-
-bb2:
- %2 = store %0 to %1a : $*Int
- dealloc_stack %as1 : $*Bool
- %3 = load %1a : $*Int
- strong_release %1 : ${ var Int }
- %r = tuple ()
- %5 = return %r : $()
-}
-
-// CHECK-LABEL: sil @nesting_and_unreachable2
-// CHECK: bb0(%0 : $Int):
-// CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
-// CHECK: bb1:
-// CHECK-NEXT: [[STACK2:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: dealloc_stack [[STACK2]]
-// CHECK-NEXT: dealloc_stack [[BOX]]
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK-NEXT: unreachable
-// CHECK: bb2:
-// CHECK: store
-// CHECK: dealloc_stack [[BOX]]
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-sil @nesting_and_unreachable2 : $(Int) -> () {
-bb0(%0 : $Int):
- %as1 = alloc_stack $Bool
- %1 = alloc_box ${ var Int }
- %1a = project_box %1 : ${ var Int }, 0
- cond_br undef, bb1, bb2
-
-bb1:
- %as2 = alloc_stack $Bool
- strong_release %1 : ${ var Int }
- dealloc_stack %as2 : $*Bool
- unreachable
-
-bb2:
- %2 = store %0 to %1a : $*Int
- dealloc_stack %as1 : $*Bool
- %3 = load %1a : $*Int
- strong_release %1 : ${ var Int }
- %r = tuple ()
- %5 = return %r : $()
-}
-
-// CHECK-LABEL: sil @nesting_and_unreachable3
-// CHECK: bb0(%0 : $Int):
-// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
-// CHECK-NEXT: [[STACK:%[0-9]+]] = alloc_stack $Bool
-// CHECK: bb1:
-// CHECK-NEXT: dealloc_stack [[STACK]]
-// CHECK-NEXT: dealloc_stack [[BOX]]
-// CHECK-NEXT: unreachable
-// CHECK: bb2:
-// CHECK: store
-// CHECK: dealloc_stack [[STACK]]
-// CHECK-NEXT: dealloc_stack [[BOX]]
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-sil @nesting_and_unreachable3 : $(Int) -> () {
-bb0(%0 : $Int):
- %1 = alloc_box ${ var Int }
- %as1 = alloc_stack $Bool
- %1a = project_box %1 : ${ var Int }, 0
- cond_br undef, bb1, bb2
-
-bb1:
- strong_release %1 : ${ var Int }
- unreachable
-
-bb2:
- %2 = store %0 to %1a : $*Int
- %3 = load %1a : $*Int
- dealloc_stack %as1 : $*Bool
- strong_release %1 : ${ var Int }
- %r = tuple ()
- %5 = return %r : $()
-}
-
-// CHECK-LABEL: sil @nesting_and_unreachable4
-// CHECK: bb0(%0 : $Int):
-// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
-// CHECK: bb1:
-// CHECK-NEXT: unreachable
-// CHECK: bb2:
-// CHECK: store
-// CHECK: dealloc_stack [[BOX]]
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-sil @nesting_and_unreachable4 : $(Int) -> () {
-bb0(%0 : $Int):
- %1 = alloc_box ${ var Int }
- %1a = project_box %1 : ${ var Int }, 0
- cond_br undef, bb1, bb2
-
-bb1:
- unreachable
-
-bb2:
- %2 = store %0 to %1a : $*Int
- %3 = load %1a : $*Int
- strong_release %1 : ${ var Int }
- %r = tuple ()
- %5 = return %r : $()
-}
-
-// CHECK-LABEL: sil @nesting_and_unreachable_critical_edge
-// CHECK: bb0(%0 : $Int):
-// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
-// CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: cond_br
-// CHECK: bb1:
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK-NEXT: br bb5
-// CHECK: bb2:
-// CHECK-NEXT: [[STACK2:%[0-9]+]] = alloc_stack $Bool
-// CHECK-NEXT: cond_br
-// CHECK: bb3:
-// CHECK-NEXT: dealloc_stack [[STACK2]]
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK-NEXT: br bb5
-// CHECK: bb4:
-// CHECK: store
-// CHECK: dealloc_stack [[STACK2]]
-// CHECK-NEXT: dealloc_stack [[STACK1]]
-// CHECK-NEXT: dealloc_stack [[BOX]]
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-// CHECK: bb5:
-// CHECK-NEXT: dealloc_stack [[BOX]]
-// CHECK-NEXT: unreachable
-sil @nesting_and_unreachable_critical_edge : $(Int) -> () {
-bb0(%0 : $Int):
- %1 = alloc_box ${ var Int }
- %as1 = alloc_stack $Bool
- %1a = project_box %1 : ${ var Int }, 0
- cond_br undef, bb1, bb3
-
-bb1:
- %as2 = alloc_stack $Bool
- cond_br undef, bb2, bb3
-
-bb2:
- %2 = store %0 to %1a : $*Int
- %3 = load %1a : $*Int
- dealloc_stack %as2 : $*Bool
- dealloc_stack %as1 : $*Bool
- strong_release %1 : ${ var Int }
- %r = tuple ()
- %5 = return %r : $()
-
-bb3:
- strong_release %1 : ${ var Int }
- unreachable
-
-}
-
diff --git a/test/SILOptimizer/definite_init_failable_initializers.swift b/test/SILOptimizer/definite_init_failable_initializers.swift
index d5b7e4f..ea5c4c8 100644
--- a/test/SILOptimizer/definite_init_failable_initializers.swift
+++ b/test/SILOptimizer/definite_init_failable_initializers.swift
@@ -40,10 +40,10 @@
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $FailableStruct
// CHECK: br bb1
// CHECK: bb1:
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[SELF]]
init?(failBeforeInitialization: ()) {
return nil
@@ -59,10 +59,10 @@
// CHECK: bb1:
// CHECK-NEXT: [[X_ADDR:%.*]] = struct_element_addr [[SELF_BOX]]
// CHECK-NEXT: strong_release [[CANARY]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[SELF]]
init?(failAfterPartialInitialization: ()) {
x = Canary()
@@ -82,10 +82,10 @@
// CHECK: bb1:
// CHECK-NEXT: [[SELF:%.*]] = struct $FailableStruct ([[CANARY1]] : $Canary, [[CANARY2]] : $Canary)
// CHECK-NEXT: release_value [[SELF]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
init?(failAfterFullInitialization: ()) {
x = Canary()
@@ -101,10 +101,10 @@
// CHECK-NEXT: br bb1
// CHECK: bb1:
// CHECK-NEXT: release_value [[CANARY]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[SELF_VALUE:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[SELF_VALUE]]
init?(failAfterWholeObjectInitializationByAssignment: ()) {
self = FailableStruct(noFail: ())
@@ -120,10 +120,10 @@
// CHECK-NEXT: br bb1
// CHECK: bb1:
// CHECK-NEXT: release_value [[NEW_SELF]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
init?(failAfterWholeObjectInitializationByDelegation: ()) {
self.init(noFail: ())
@@ -146,15 +146,14 @@
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.some!enumelt.1, [[SELF_VALUE]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableStruct>)
//
// CHECK: [[FAIL_EPILOG_BB]]:
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br [[EPILOG_BB]]([[NEW_SELF]] : $Optional<FailableStruct>)
//
// CHECK: [[EPILOG_BB]]([[NEW_SELF:%.*]] : $Optional<FailableStruct>)
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// Optional to optional
init?(failDuringDelegation: ()) {
@@ -205,11 +204,11 @@
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $FailableAddrOnlyStruct<T>
// CHECK: br bb1
// CHECK: bb1:
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: inject_enum_addr %0
// CHECK-NEXT: br bb2
// CHECK: bb2:
-// CHECK: return
+// CHECK: dealloc_stack [[SELF_BOX]]
+// CHECK-NEXT: return
init?(failBeforeInitialization: ()) {
return nil
}
@@ -228,11 +227,11 @@
// CHECK: bb1:
// CHECK-NEXT: [[X_ADDR:%.*]] = struct_element_addr [[SELF_BOX]]
// CHECK-NEXT: destroy_addr [[X_ADDR]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: inject_enum_addr %0
// CHECK-NEXT: br bb2
// CHECK: bb2:
-// CHECK: return
+// CHECK: dealloc_stack [[SELF_BOX]]
+// CHECK-NEXT: return
init?(failAfterPartialInitialization: ()) {
x = T()
return nil
@@ -258,11 +257,11 @@
// CHECK-NEXT: br bb1
// CHECK: bb1:
// CHECK-NEXT: destroy_addr [[SELF_BOX]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: inject_enum_addr %0
// CHECK-NEXT: br bb2
// CHECK: bb2:
-// CHECK: return
+// CHECK: dealloc_stack [[SELF_BOX]]
+// CHECK-NEXT: return
init?(failAfterFullInitialization: ()) {
x = T()
y = T()
@@ -528,15 +527,14 @@
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<ThrowStruct>, #Optional.some!enumelt.1, [[SELF_VALUE]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<ThrowStruct>)
//
// CHECK: [[FAIL_EPILOG_BB]]:
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<ThrowStruct>, #Optional.none!enumelt
// CHECK-NEXT: br [[EPILOG_BB]]([[NEW_SELF]] : $Optional<ThrowStruct>)
//
// CHECK: [[EPILOG_BB]]([[NEW_SELF:%.*]] : $Optional<ThrowStruct>):
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]] : $Optional<ThrowStruct>
//
// CHECK: [[TRY_APPLY_FAIL_TRAMPOLINE_BB:bb[0-9]+]]:
@@ -748,10 +746,10 @@
// CHECK: bb1:
// CHECK-NEXT: [[METATYPE:%.*]] = value_metatype $@thick FailableBaseClass.Type, %0 : $FailableBaseClass
// CHECK-NEXT: dealloc_partial_ref %0 : $FailableBaseClass, [[METATYPE]] : $@thick FailableBaseClass.Type
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[RESULT:%.*]] = enum $Optional<FailableBaseClass>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[RESULT]]
convenience init?(failBeforeDelegation: ()) {
return nil
@@ -767,10 +765,10 @@
// CHECK-NEXT: br bb1
// CHECK: bb1:
// CHECK-NEXT: strong_release [[NEW_SELF]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[RESULT:%.*]] = enum $Optional<FailableBaseClass>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[RESULT]]
convenience init?(failAfterDelegation: ()) {
self.init(noFail: ())
@@ -794,15 +792,14 @@
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableBaseClass>, #Optional.some!enumelt.1, [[SELF_VALUE]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableBaseClass>)
//
// CHECK: [[FAIL_TRAMPOLINE_BB]]:
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableBaseClass>, #Optional.none!enumelt
// CHECK-NEXT: br [[EPILOG_BB]]([[NEW_SELF]] : $Optional<FailableBaseClass>)
//
// CHECK: [[EPILOG_BB]]([[NEW_SELF:%.*]] : $Optional<FailableBaseClass>):
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// Optional to optional
convenience init?(failDuringDelegation: ()) {
@@ -843,10 +840,10 @@
// CHECK: bb1:
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick FailableDerivedClass.Type
// CHECK-NEXT: dealloc_partial_ref %0 : $FailableDerivedClass, [[METATYPE]] : $@thick FailableDerivedClass.Type
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[RESULT:%.*]] = enum $Optional<FailableDerivedClass>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[RESULT]]
init?(derivedFailBeforeDelegation: ()) {
return nil
@@ -874,15 +871,14 @@
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_ref_cast [[BASE_SELF_VALUE]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableDerivedClass>, #Optional.some!enumelt.1, [[SELF_VALUE]]
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableDerivedClass>)
//
// CHECK: [[FAIL_TRAMPOLINE_BB]]:
-// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableDerivedClass>, #Optional.none!enumelt
// CHECK-NEXT: br [[EPILOG_BB]]([[NEW_SELF]] : $Optional<FailableDerivedClass>)
//
// CHECK: [[EPILOG_BB]]([[NEW_SELF:%.*]] : $Optional<FailableDerivedClass>):
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]] : $Optional<FailableDerivedClass>
init?(derivedFailDuringDelegation: ()) {
self.otherMember = Canary()
diff --git a/test/SILOptimizer/definite_init_protocol_init.swift b/test/SILOptimizer/definite_init_protocol_init.swift
index f24d78b..b109ff3 100644
--- a/test/SILOptimizer/definite_init_protocol_init.swift
+++ b/test/SILOptimizer/definite_init_protocol_init.swift
@@ -100,8 +100,8 @@
// CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [initialization] [[SELF]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: copy_addr [take] [[SELF]] to [initialization] %0
-// CHECK-NEXT: dealloc_stack [[SELF]]
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: dealloc_stack [[SELF]]
// CHECK-NEXT: return [[RESULT]]
init(upper: Int) {
self.init(middle: upper)
diff --git a/test/SILOptimizer/sroa_unreferenced_members.swift b/test/SILOptimizer/sroa_unreferenced_members.swift
index 9c7775c..cce1ea7 100644
--- a/test/SILOptimizer/sroa_unreferenced_members.swift
+++ b/test/SILOptimizer/sroa_unreferenced_members.swift
@@ -3,7 +3,7 @@
import gizmo
// CHECK: ModifyStruct
-// CHECK: = alloc_stack $Drill
+// CHECK: %1 = alloc_stack $Drill
// CHECK: ret
func ModifyStruct(inDrill : Drill) -> Int32 {
var D : Drill = inDrill
diff --git a/test/multifile/Inputs/protocol-conformance/rdar31302713.swift b/test/multifile/Inputs/protocol-conformance/rdar31302713.swift
new file mode 100644
index 0000000..5c8e442
--- /dev/null
+++ b/test/multifile/Inputs/protocol-conformance/rdar31302713.swift
@@ -0,0 +1,24 @@
+public protocol Animal {
+ associatedtype AnimalSnackType : AnimalSnack
+ func snack(on: AnimalSnackType)
+}
+
+public protocol AnimalSnack {
+ associatedtype EatWith
+ func eat(with: EatWith)
+}
+
+extension AnimalSnack where EatWith : Animal {}
+
+public protocol FurryAnimal : Animal {
+ associatedtype Fangs : Animal
+ func bite(with: Fangs)
+}
+
+extension FurryAnimal {
+ public func snack(on: FurryAnimalSnack<Self>) {}
+}
+
+public struct FurryAnimalSnack<T : FurryAnimal> : AnimalSnack {
+ public func eat(with: T) {}
+}
diff --git a/test/multifile/protocol-conformance-rdar31302713.swift b/test/multifile/protocol-conformance-rdar31302713.swift
new file mode 100644
index 0000000..b2a8a01
--- /dev/null
+++ b/test/multifile/protocol-conformance-rdar31302713.swift
@@ -0,0 +1,6 @@
+// RUN: %target-swift-frontend -emit-ir -primary-file %s %S/Inputs/protocol-conformance/rdar31302713.swift -module-name animal_snack
+
+public struct FunctionalFurryAnimal<Fangs : Animal> : FurryAnimal
+ where Fangs.AnimalSnackType.EatWith == Fangs {
+ public func bite(with: Fangs) {}
+}