Skip to content

[Optimize] Move dead partial apply elimination to mandatory combine #28536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e069f5f
Move partial_apply closure cleanup into mandatory combine
zoecarver Dec 2, 2019
112999f
Add comments
zoecarver Dec 3, 2019
1ac0a9a
Format
zoecarver Dec 3, 2019
f354e25
Merge branch 'master' into optimize/dead-closure-in-mand-combine
zoecarver Dec 17, 2019
833ca19
Fix failing tests
zoecarver Dec 17, 2019
7805727
Merge branch 'master' into optimize/dead-closure-in-mand-combine
zoecarver Dec 30, 2019
35652ec
Fix mandatory_inlining.sil
zoecarver Dec 31, 2019
b7eef42
Rename tests
zoecarver Dec 31, 2019
fd55891
stash: add load visitor and refactor
zoecarver Jan 2, 2020
3824e86
Use lambda to remove instructions
zoecarver Jan 2, 2020
29e35da
Move stripCopiesAndBorrows and cleanupLoadedCalleeValue into InstOptU…
zoecarver Jan 2, 2020
a383b76
Fix crash and remove todos
zoecarver Jan 2, 2020
e6543b5
Remove unused ClosureCleanup from mandatory inlining
zoecarver Jan 2, 2020
503cbc0
Merge branch 'master' into optimize/dead-closure-in-mand-combine
zoecarver Feb 17, 2020
d8c13c2
Merge branch 'master' into optimize/dead-closure-in-mand-combine
zoecarver Feb 18, 2020
7fe24f0
Update instruction deleter callback to actually erease instructions s…
zoecarver Feb 21, 2020
ac789a1
Update mand inline sil tests after breaking closure cleanup into mand…
zoecarver Feb 21, 2020
3e08baa
Removed unused member: tryRemoveUnused
zoecarver Feb 21, 2020
25d99d7
Fix remaining tests
zoecarver Feb 22, 2020
9607682
Run formatter over code
zoecarver Feb 22, 2020
4e9ad8a
Fix still failing tests
zoecarver Feb 22, 2020
006861d
Merge branch 'master' into optimize/dead-closure-in-mand-combine
zoecarver Mar 3, 2020
5fe078a
Update based on review:
zoecarver Mar 15, 2020
f454769
Reset tests / mand inline changes to master
zoecarver Mar 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions lib/SILOptimizer/Mandatory/MandatoryCombine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#define DEBUG_TYPE "sil-mandatory-combiner"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/STLExtras.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/InstructionUtils.h"
#include "swift/SIL/SILInstructionWorklist.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
Expand Down Expand Up @@ -129,6 +131,11 @@ class MandatoryCombiner final
/// Base visitor that does not do anything.
SILInstruction *visitSILInstruction(SILInstruction *) { return nullptr; }
SILInstruction *visitApplyInst(ApplyInst *instruction);
SILInstruction *visitPartialApplyInst(PartialApplyInst *i);
SILInstruction *visitLoadInst(LoadInst *i);
SILInstruction *visitThinToThickFunctionInst(ThinToThickFunctionInst *i);
SILInstruction *visitStoreInst(StoreInst *i);
SILInstruction *visitConvertFunctionInst(ConvertFunctionInst *i);
};

} // end anonymous namespace
Expand Down Expand Up @@ -156,6 +163,7 @@ void MandatoryCombiner::addReachableCodeToWorklist(SILFunction &function) {
++iterator;

if (isInstructionTriviallyDead(instruction)) {
instModCallbacks.deleteInst(instruction);
continue;
}

Expand Down Expand Up @@ -199,10 +207,12 @@ bool MandatoryCombiner::doOneIteration(SILFunction &function,
instructionDescription
#endif
);
madeChange = true;
}

for (SILInstruction *instruction : instructionsPendingDeletion) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this removed?

worklist.eraseInstFromFunction(*instruction);
madeChange = true;
}
instructionsPendingDeletion.clear();

Expand Down Expand Up @@ -284,6 +294,147 @@ SILInstruction *MandatoryCombiner::visitApplyInst(ApplyInst *instruction) {
return nullptr;
}

template <class InstT> static FunctionRefInst *getRemovableRef(InstT *i) {
// If the only use of the function_ref is us, then remove it.
auto funcRef = dyn_cast<FunctionRefInst>(i->getCallee());
if (funcRef &&
(funcRef->use_empty() ||
(funcRef->getSingleUse() && funcRef->getSingleUse()->getUser() == i))) {
return funcRef;
}
return nullptr;
}

SILInstruction *MandatoryCombiner::visitStoreInst(StoreInst *store) {
// First optimization: try to promote store src to loads.
LoadInst *load = nullptr;
for (auto *use : getNonDebugUses(store->getDest())) {
if (use->getUser() == store)
continue;

if (auto loadUse = dyn_cast<LoadInst>(use->getUser())) {
if (load) {
load = nullptr;
break;
}
load = loadUse;
}
}

// If we can promote the load, do so.
if (load && std::find(instructionsPendingDeletion.begin(),
instructionsPendingDeletion.end(), load) == instructionsPendingDeletion.end()) {
if (load->getOwnershipQualifier() == LoadOwnershipQualifier::Copy) {
auto copy = SILBuilderWithScope(load)
.createCopyValue(load->getLoc(), store->getSrc());
load->replaceAllUsesWith(copy);
} else if (load->getOwnershipQualifier() == LoadOwnershipQualifier::Take) {
SILBuilderWithScope(load)
.createDestroyAddr(load->getLoc(), load->getOperand());
load->replaceAllUsesWith(store->getSrc());
} else
load->replaceAllUsesWith(store->getSrc());
instModCallbacks.deleteInst(load);
}

// Now try to promote alloc_box/project_box.
auto pbi = dyn_cast<ProjectBoxInst>(store->getDest());
if (!pbi)
return nullptr;

for (auto *use : getNonDebugUses(pbi)) {
if (use->getUser() != store)
return nullptr;
}

auto abi = dyn_cast<AllocBoxInst>(pbi->getOperand());
if (!abi)
return nullptr;

SmallVector<SILInstruction*, 2> instToDestroy;
for (auto *use : abi->getUses()) {
auto user = use->getUser();

if (user == pbi)
continue;

if (!isa<DestroyValueInst>(user) && !isa<StrongReleaseInst>(user))
return nullptr;

instToDestroy.push_back(user);
}

// We know all we're replacing is destroy instructions so if it's trivial just
// remove the uses.
if (store->getOwnershipQualifier() == StoreOwnershipQualifier::Trivial) {
// We need to collect store and pbi first.
instModCallbacks.deleteInst(store);
instModCallbacks.deleteInst(pbi);
for (auto *use : abi->getUses()) {
auto user = use->getUser();
if (user == store || user == pbi)
continue;
instModCallbacks.deleteInst(user);
}
} else {
abi->replaceAllUsesWith(store->getSrc());
instModCallbacks.deleteInst(store);
instModCallbacks.deleteInst(pbi);
}

instModCallbacks.deleteInst(abi);
return nullptr;
}

SILInstruction *MandatoryCombiner::visitLoadInst(LoadInst *i) {
// Remove trivially dead loads. We can remove loads where the only use is
// destroy_values.
SmallVector<SILInstruction*, 2> destroysToDestroy;
for (auto *use : i->getUses()) {
if (!isa<DestroyValueInst>(use->getUser()))
return nullptr;
destroysToDestroy.push_back(use->getUser());
}
std::for_each(destroysToDestroy.begin(), destroysToDestroy.end(),
instModCallbacks.deleteInst);
instModCallbacks.deleteInst(i);
return nullptr;
}

SILInstruction *MandatoryCombiner::visitConvertFunctionInst(ConvertFunctionInst *convFunc) {
if (isInstructionTriviallyDead(convFunc)) {
// We'll let dead code elimination do the rest
instModCallbacks.deleteInst(convFunc);
}

return nullptr;
}

/// Try to remove partial applies that are no longer used
SILInstruction *MandatoryCombiner::visitPartialApplyInst(PartialApplyInst *i) {
auto *ref = getRemovableRef(i);
if (tryDeleteDeadClosure(i, instModCallbacks, /*needKeepArgsAlive=*/false)) {
if (ref) {
instModCallbacks.deleteInst(ref);
}
}

return nullptr;
}

/// Try to remove thing to thick instructions that are no longer used
SILInstruction *
MandatoryCombiner::visitThinToThickFunctionInst(ThinToThickFunctionInst *i) {
auto *ref = getRemovableRef(i);
if (tryDeleteDeadClosure(i, instModCallbacks, /*needKeepArgsAlive=*/false)) {
if (ref) {
instModCallbacks.deleteInst(ref);
}
}

return nullptr;
}

//===----------------------------------------------------------------------===//
// Top Level Entrypoint
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion test/DebugInfo/mandatoryinlining-wrongdebugscope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: -Xllvm -sil-print-debuginfo -o /dev/null 2>&1 | %FileCheck %s

// CHECK: destroy_value {{.*}} : $@callee_guaranteed () -> (), loc {{.*}}:21:5, scope [[SCOPE:[0-9]+]]
// CHECK: destroy_value {{.*}} : $@callee_guaranteed () -> @out (), loc {{.*}}:21:5, scope [[SCOPE]]
// CHECK: destroy_value {{.*}} : $@callee_guaranteed () -> (), loc {{.*}}:21:5, scope [[SCOPE]]
// CHECK: destroy_value {{.*}} : $@callee_guaranteed () -> (), loc {{.*}}:21:5, scope [[SCOPE]]

func patatino<d, i>(_ function: @escaping (d) -> i, g: d...) -> () -> i {
Expand Down
16 changes: 6 additions & 10 deletions test/IRGen/big_types_corner_cases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,15 @@ public func enumCallee(_ x: LargeEnum) {
case .Empty2: break
}
}
// CHECK-LABEL-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s22big_types_corner_cases10enumCalleeyAA9LargeEnumOF"(%T22big_types_corner_cases9LargeEnumO* noalias nocapture dereferenceable({{.*}}) %0) #0 {
// CHECK-64: alloca %T22big_types_corner_cases9LargeEnumO05InnerF0O
// CHECK-64: alloca %T22big_types_corner_cases9LargeEnumO
// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64
// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64
// CHECK-64: $ss5print_9separator10terminatoryypd_S2StF
// CHECK-LABEL-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s22big_types_corner_cases10enumCalleeyyAA9LargeEnumOF"(%T22big_types_corner_cases9LargeEnumO* noalias nocapture dereferenceable(33) %0) #0 {
// CHECK-64: call %T22big_types_corner_cases9LargeEnumO
// CHECK-64: call %T22big_types_corner_cases9LargeEnumO05InnerF0O*
// CHECK-64: call swiftcc void @"$ss5print_9separator10terminatoryypd_S2StF"
// CHECK-64: ret void

// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal swiftcc void @"$s22big_types_corner_cases8SuperSubC1fyyFAA9BigStructVycfU_"(%T22big_types_corner_cases9BigStructV* noalias nocapture sret %0, %T22big_types_corner_cases8SuperSubC* %1)
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} hidden swiftcc void @"$s22big_types_corner_cases9SuperBaseC4boomAA9BigStructVyF"(%T22big_types_corner_cases9BigStructV* noalias nocapture sret %0, %T22big_types_corner_cases9SuperBaseC* swiftself %1)
// CHECK-64: [[ALLOC1:%.*]] = alloca %T22big_types_corner_cases9BigStructV
// CHECK-64: [[ALLOC2:%.*]] = alloca %T22big_types_corner_cases9BigStructV
// CHECK-64: [[ALLOC3:%.*]] = alloca %T22big_types_corner_cases9BigStructVSg
// CHECK-64: call swiftcc void @"$s22big_types_corner_cases9SuperBaseC4boomAA9BigStructVyF"(%T22big_types_corner_cases9BigStructV* noalias nocapture sret [[ALLOC1]], %T22big_types_corner_cases9SuperBaseC* swiftself {{.*}})
// CHECK-64: call swiftcc void @"$s22big_types_corner_cases9BigStructVACycfC"(%T22big_types_corner_cases9BigStructV* noalias nocapture sret [[ALLOC1]])
// CHECK: ret void
class SuperBase {
func boom() -> BigStruct {
Expand Down
44 changes: 9 additions & 35 deletions test/IRGen/partial_apply.sil
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
// RUN: %target-swift-frontend %s -Onone -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize

// REQUIRES: CPU=x86_64

Expand Down Expand Up @@ -387,15 +387,9 @@ sil public_external @receive_closure : $@convention(thin) <C where C : Base> (@o
// CHECK: [[CTX:%.*]] = bitcast %T13partial_apply4BaseC* %0 to %swift.refcounted*
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s13partial_apply3SubCMa"(i64 0)
// CHECK: [[TYPE:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
// CHECK: call swiftcc void @receive_closure(i8* bitcast (%T13partial_apply3SubC* (%swift.refcounted*)* @"$s26parametric_casting_closureTA.{{[0-9]+}}" to i8*), %swift.refcounted* [[CTX]], %swift.type* [[TYPE]])
// CHECK: call swiftcc void @receive_closure(i8* bitcast (%T13partial_apply3SubC* (%swift.refcounted*)* @"$s26parametric_casting_closureTA" to i8*), %swift.refcounted* [[CTX]], %swift.type* [[TYPE]])

// CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @"$s26parametric_casting_closureTA"(%T13partial_apply4BaseC* %0, %swift.refcounted* swiftself %1)
// CHECK: [[RES:%.*]] = tail call swiftcc %T13partial_apply4BaseC* @parametric_casting_closure
// CHECK: [[CASTED:%.*]] = bitcast %T13partial_apply4BaseC* [[RES]] to %T13partial_apply3SubC*
// CHECK: ret %T13partial_apply3SubC* [[CASTED]]


// CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @"$s26parametric_casting_closureTA.{{[0-9]+}}"(%swift.refcounted* swiftself %0)
// CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @"$s26parametric_casting_closureTA"(%swift.refcounted* swiftself %0)
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s13partial_apply3SubCMa"(i64 0)
// CHECK: [[TYPE:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
// CHECK: [[CTX:%.*]] = bitcast %swift.refcounted* %0 to %T13partial_apply4BaseC*
Expand All @@ -420,8 +414,8 @@ sil public_external @partial_empty_box : $@convention(thin) (@owned <τ_0_0> { v
sil @empty_box : $@convention(thin) () -> () {
entry:
// CHECK: [[BOX:%.*]] = call {{.*}}swift_allocEmptyBox
// CHECK: store %swift.refcounted* [[BOX]]
// CHECK: store %swift.opaque* undef
// CHECK-NEXT: call void @swift_release(%swift.refcounted* [[BOX]])
// CHECK-NEXT: ret
%b = alloc_box $<τ_0_0> { var τ_0_0 } <()>
%ba = project_box %b : $<τ_0_0> { var τ_0_0 } <()>, 0
%f = function_ref @partial_empty_box : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <()>, @inout_aliasable ()) -> ()
Expand All @@ -443,30 +437,10 @@ bb0(%0 : $Int):
return %result : $()
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @partial_apply_complex_generic_function(i64 %0, %swift.type* %T, i8** %T.P2, i8** %T.Y.P2)
// CHECK: [[T0:%.*]] = call noalias %swift.refcounted* @swift_allocObject(%swift.type* {{.*}}, i64 48, i64 7)
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.refcounted* [[T0]] to <{ %swift.refcounted, [24 x i8], %TSi }>*
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, <{ %swift.refcounted, [24 x i8], %TSi }>* [[T1]], i32 0, i32 1
// CHECK-NEXT: [[BUFFER:%.*]] = bitcast [24 x i8]* [[T2]] to %swift.type**
// CHECK-NEXT: store %swift.type* %T, %swift.type** [[BUFFER]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 1
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: store i8** %T.P2, i8*** [[T1]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 2
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: store i8** %T.Y.P2, i8*** [[T1]], align 8

// CHECK-LABEL: define internal swiftcc void @"$s24complex_generic_functionTA"(%swift.refcounted* swiftself %0)
// CHECK: [[T0:%.*]] = bitcast %swift.refcounted* %0 to <{ %swift.refcounted, [24 x i8], %TSi }>*
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, <{ %swift.refcounted, [24 x i8], %TSi }>* [[T0]], i32 0, i32 1
// CHECK-NEXT: [[BUFFER:%.*]] = bitcast [24 x i8]* [[T1]] to %swift.type**
// CHECK-NEXT: %T = load %swift.type*, %swift.type** [[BUFFER]], align 8
// CHECK-NEXT: store %swift.type* %T, %swift.type**
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 1
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: %T.P2 = load i8**, i8*** [[T1]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 2
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8***
// CHECK-NEXT: %T.Y.P2 = load i8**, i8*** [[T1]], align 8
// CHECK-NEXT: entry
// CHECK-NEXT: alloca
// CHECK-NEXT: store
// CHECK-NEXT: ret

struct ComplexBoundedType<T: P2> {}

Expand Down
31 changes: 11 additions & 20 deletions test/IRGen/partial_apply_forwarder.sil
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ bb0(%0 : $E):
sil hidden_external @unspecialized_uncurried : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed E) -> @owned D<τ_0_0>


// CHECK-LABEL: define internal swiftcc void @"$s7takingPTA"(%swift.refcounted*
// CHECK: [[CONTEXT:%.*]] = alloca %swift.refcounted*
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s23partial_apply_forwarder1CCMa"([[INT]] 0)
// CHECK: [[TYPE:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
// CHECK: store %swift.refcounted* %0, %swift.refcounted** [[CONTEXT]]
// CHECK: [[CAST:%.*]] = bitcast %swift.refcounted** [[CONTEXT]] to %swift.opaque*
// CHECK: call swiftcc void @takingP(%swift.type* [[TYPE]], i8**{{.*}}$s23partial_apply_forwarder1CCAA1PAAWP{{.*}}, %swift.opaque* {{.*}} swiftself [[CAST]]
// CHECK: ret
// CHECK-LABEL: define hidden swiftcc void @reabstract_context(%T23partial_apply_forwarder1CC* %0)
// CHECK-NEXT: entry
// CHECK-NEXT: alloca
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8
// CHECK-NEXT: store
// CHECK-NEXT: load
// CHECK-NEXT: call void bitcast
// CHECK-NEXT: bitcast %T23partial_apply_forwarder1CC** %1 to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8
// CHECK-NEXT: ret
sil hidden_external @takingP : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()

sil hidden @reabstract_context : $@convention(thin) (@owned C) -> () {
Expand Down Expand Up @@ -149,18 +152,6 @@ bb0(%0 : $*τ_0_1, %2: $EmptyType):
// CHECK: call noalias %swift.refcounted* @swift_allocObject(%swift.type* [[WBTY]]
// CHECK: ret void

// CHECK-LABEL: define internal swiftcc void @"$s7takingQTA.1"(%T23partial_apply_forwarder7WeakBoxC* %0, %swift.refcounted* swiftself %1)
// CHECK: entry:
// CHECK: [[TYADDR:%.*]] = getelementptr inbounds %T23partial_apply_forwarder7WeakBoxC, %T23partial_apply_forwarder7WeakBoxC* %0
// CHECK: [[TY:%.*]] = load %swift.type*, %swift.type** [[TYADDR]]
// CHECK: [[CAST:%.*]] = bitcast %T23partial_apply_forwarder7WeakBoxC* %0 to %T23partial_apply_forwarder7WeakBoxC.1*
// CHECK: [[TYPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
// CHECK: [[TYPARAM:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[TYPARAMSADDR]], {{(i64 10|i32 13)}}
// CHECK: %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[TYPARAM]]
// CHECK: [[WITNESS:%.*]] = call i8** @swift_getWitnessTable
// CHECK: tail call swiftcc void @takingQ(%T23partial_apply_forwarder7WeakBoxC.1* [[CAST]], i8** [[WITNESS]])
// CHECK: ret void

sil public @bind_polymorphic_param_from_forwarder_parameter : $@convention(thin) <τ_0_1>(@in τ_0_1) -> () {
bb0(%0 : $*τ_0_1):
%1 = alloc_ref $WeakBox<BaseProducer<τ_0_1>>
Expand Down
Loading