Skip to content

Commit 11de736

Browse files
authored
[AutoDiff] Unwrap the top level of linear map tuple when it is possible (swiftlang#63770)
This essentially passes the members of a linear map tuple as individual arguments. It yields few nice simplifications: * No linear map tuples at all for getters / setters * No tuple formation / deconstruction around pullbacks * Pullbacks with loops still use heap-allocated tuples
1 parent d77db25 commit 11de736

File tree

7 files changed

+84
-60
lines changed

7 files changed

+84
-60
lines changed

lib/SILOptimizer/Differentiation/PullbackCloner.cpp

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class PullbackCloner::Implementation final
9090
/// elements destructured from the linear map basic block argument. In the
9191
/// beginning of each pullback basic block, the block's pullback struct is
9292
/// destructured into individual elements stored here.
93-
llvm::DenseMap<SILBasicBlock*, SILInstructionResultArray> pullbackTupleElements;
93+
llvm::DenseMap<SILBasicBlock*, SmallVector<SILValue, 4>> pullbackTupleElements;
9494

9595
/// Mapping from original basic blocks and successor basic blocks to
9696
/// corresponding pullback trampoline basic blocks. Trampoline basic blocks
@@ -163,8 +163,19 @@ class PullbackCloner::Implementation final
163163
auto *pbTupleTyple = getPullbackInfo().getLinearMapTupleType(origBB);
164164
assert(pbTupleTyple->getNumElements() == values.size() &&
165165
"The number of pullback tuple fields must equal the number of "
166-
"pullback struct element values");
167-
auto res = pullbackTupleElements.insert({origBB, values});
166+
"pullback tuple element values");
167+
auto res = pullbackTupleElements.insert({origBB, { values.begin(), values.end() }});
168+
(void)res;
169+
assert(res.second && "A pullback tuple element already exists!");
170+
}
171+
172+
void initializePullbackTupleElements(SILBasicBlock *origBB,
173+
const llvm::ArrayRef<SILArgument *> &values) {
174+
auto *pbTupleTyple = getPullbackInfo().getLinearMapTupleType(origBB);
175+
assert(pbTupleTyple->getNumElements() == values.size() &&
176+
"The number of pullback tuple fields must equal the number of "
177+
"pullback tuple element values");
178+
auto res = pullbackTupleElements.insert({origBB, { values.begin(), values.end() }});
168179
(void)res;
169180
assert(res.second && "A pullback struct element already exists!");
170181
}
@@ -1917,34 +1928,36 @@ bool PullbackCloner::Implementation::run() {
19171928
builder.setInsertionPoint(pullbackBB);
19181929
// Obtain the context object, if any, and the top-level subcontext, i.e.
19191930
// the main pullback struct.
1920-
SILValue mainPullbackTuple;
19211931
if (getPullbackInfo().hasLoops()) {
19221932
// The last argument is the context object (`Builtin.NativeObject`).
19231933
contextValue = pullbackBB->getArguments().back();
19241934
assert(contextValue->getType() ==
19251935
SILType::getNativeObjectType(getASTContext()));
1926-
// Load the pullback struct.
1936+
// Load the pullback context.
19271937
auto subcontextAddr = emitProjectTopLevelSubcontext(
19281938
builder, pbLoc, contextValue, pbTupleLoweredType);
1929-
mainPullbackTuple = builder.createLoad(
1939+
SILValue mainPullbackTuple = builder.createLoad(
19301940
pbLoc, subcontextAddr,
19311941
pbTupleLoweredType.isTrivial(getPullback()) ?
19321942
LoadOwnershipQualifier::Trivial : LoadOwnershipQualifier::Take);
1943+
auto *dsi = builder.createDestructureTuple(pbLoc, mainPullbackTuple);
1944+
initializePullbackTupleElements(origBB, dsi->getAllResults());
19331945
} else {
19341946
// Obtain and destructure pullback struct elements.
1935-
mainPullbackTuple = pullbackBB->getArguments().back();
1936-
assert(mainPullbackTuple->getType() == pbTupleLoweredType);
1947+
unsigned numVals = pbTupleLoweredType.getAs<TupleType>()->getNumElements();
1948+
initializePullbackTupleElements(origBB,
1949+
pullbackBB->getArguments().take_back(numVals));
19371950
}
19381951

1939-
auto *dsi = builder.createDestructureTuple(pbLoc, mainPullbackTuple);
1940-
initializePullbackTupleElements(origBB, dsi->getResults());
19411952
continue;
19421953
}
1954+
19431955
// Get all active values in the original block.
19441956
// If the original block has no active values, continue.
19451957
auto &bbActiveValues = activeValues[origBB];
19461958
if (bbActiveValues.empty())
19471959
continue;
1960+
19481961
// Otherwise, if the original block has active values:
19491962
// - For each active buffer in the original block, allocate a new local
19501963
// buffer in the pullback entry. (All adjoint buffers are allocated in
@@ -2008,11 +2021,17 @@ bool PullbackCloner::Implementation::run() {
20082021
}
20092022

20102023
auto *pullbackEntry = pullback.getEntryBlock();
2024+
auto pbTupleLoweredType =
2025+
remapType(getPullbackInfo().getLinearMapTupleLoweredType(originalExitBlock));
2026+
unsigned numVals = (getPullbackInfo().hasLoops() ?
2027+
1 : pbTupleLoweredType.getAs<TupleType>()->getNumElements());
2028+
(void)numVals;
2029+
20112030
// The pullback function has type:
2012-
// `(seed0, seed1, ..., exit_pb_struct|context_obj) -> (d_arg0, ..., d_argn)`.
2031+
// `(seed0, seed1, ..., (exit_pb_tuple_el0, ..., )|context_obj) -> (d_arg0, ..., d_argn)`.
20132032
auto pbParamArgs = pullback.getArgumentsWithoutIndirectResults();
2014-
assert(getConfig().resultIndices->getNumIndices() == pbParamArgs.size() - 1 &&
2015-
pbParamArgs.size() >= 2);
2033+
assert(getConfig().resultIndices->getNumIndices() == pbParamArgs.size() - numVals &&
2034+
pbParamArgs.size() >= 1);
20162035
// Assign adjoints for original result.
20172036
builder.setCurrentDebugScope(
20182037
remapScope(originalExitBlock->getTerminator()->getDebugScope()));
@@ -2637,9 +2656,9 @@ bool PullbackCloner::Implementation::runForSemanticMemberGetter() {
26372656

26382657
// Get getter argument and result values.
26392658
// Getter type: $(Self) -> Result
2640-
// Pullback type: $(Result', PB_Struct|Context) -> Self'
2659+
// Pullback type: $(Result') -> Self'
26412660
assert(original.getLoweredFunctionType()->getNumParameters() == 1);
2642-
assert(pullback.getLoweredFunctionType()->getNumParameters() == 2);
2661+
assert(pullback.getLoweredFunctionType()->getNumParameters() == 1);
26432662
assert(pullback.getLoweredFunctionType()->getNumResults() == 1);
26442663
SILValue origSelf = original.getArgumentsWithoutIndirectResults().front();
26452664

@@ -2752,10 +2771,10 @@ bool PullbackCloner::Implementation::runForSemanticMemberSetter() {
27522771

27532772
// Get setter argument values.
27542773
// Setter type: $(inout Self, Argument) -> ()
2755-
// Pullback type (wrt self): $(inout Self', PB_Struct) -> ()
2756-
// Pullback type (wrt both): $(inout Self', PB_Struct) -> Argument'
2774+
// Pullback type (wrt self): $(inout Self') -> ()
2775+
// Pullback type (wrt both): $(inout Self') -> Argument'
27572776
assert(original.getLoweredFunctionType()->getNumParameters() == 2);
2758-
assert(pullback.getLoweredFunctionType()->getNumParameters() == 2);
2777+
assert(pullback.getLoweredFunctionType()->getNumParameters() == 1);
27592778
assert(pullback.getLoweredFunctionType()->getNumResults() == 0 ||
27602779
pullback.getLoweredFunctionType()->getNumResults() == 1);
27612780

lib/SILOptimizer/Differentiation/VJPCloner.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class VJPCloner::Implementation final
112112
void emitLinearMapContextInitializationIfNeeded() {
113113
if (!pullbackInfo.hasLoops())
114114
return;
115+
115116
// Get linear map struct size.
116117
auto *returnBB = &*original->findReturnBB();
117118
auto pullbackTupleType =
@@ -171,6 +172,7 @@ class VJPCloner::Implementation final
171172
/// Build a pullback tuple value for the given original terminator
172173
/// instruction.
173174
TupleInst *buildPullbackValueTupleValue(TermInst *termInst);
175+
llvm::SmallVector<SILValue, 8> getPullbackValues(SILBasicBlock *origBB);
174176

175177
/// Build a predecessor enum instance using the given builder for the given
176178
/// original predecessor/successor blocks and pullback struct value.
@@ -221,9 +223,8 @@ class VJPCloner::Implementation final
221223
void visitReturnInst(ReturnInst *ri) {
222224
Builder.setCurrentDebugScope(getOpScope(ri->getDebugScope()));
223225
auto loc = ri->getOperand().getLoc();
224-
// Build pullback struct value for original block.
226+
// Build pullback tuple value for original block.
225227
auto *origExit = ri->getParent();
226-
auto *pbTupleVal = buildPullbackValueTupleValue(ri);
227228

228229
// Get the value in the VJP corresponding to the original result.
229230
auto *origRetInst = cast<ReturnInst>(origExit->getTerminator());
@@ -237,7 +238,9 @@ class VJPCloner::Implementation final
237238

238239
// Prepare partial application arguments.
239240
SILValue partialApplyArg;
241+
PartialApplyInst *pullbackPartialApply;
240242
if (borrowedPullbackContextValue) {
243+
auto *pbTupleVal = buildPullbackValueTupleValue(ri);
241244
// Initialize the top-level subcontext buffer with the top-level pullback
242245
// tuple.
243246
auto addr = emitProjectTopLevelSubcontext(
@@ -246,15 +249,17 @@ class VJPCloner::Implementation final
246249
loc, pbTupleVal, addr,
247250
pbTupleVal->getType().isTrivial(*pullback) ?
248251
StoreOwnershipQualifier::Trivial : StoreOwnershipQualifier::Init);
249-
partialApplyArg = pullbackContextValue;
252+
250253
Builder.createEndBorrow(loc, borrowedPullbackContextValue);
254+
pullbackPartialApply = Builder.createPartialApply(
255+
loc, pullbackRef, vjpSubstMap, {pullbackContextValue},
256+
ParameterConvention::Direct_Guaranteed);
251257
} else {
252-
partialApplyArg = pbTupleVal;
258+
pullbackPartialApply = Builder.createPartialApply(
259+
loc, pullbackRef, vjpSubstMap, getPullbackValues(origExit),
260+
ParameterConvention::Direct_Guaranteed);
253261
}
254262

255-
auto *pullbackPartialApply = Builder.createPartialApply(
256-
loc, pullbackRef, vjpSubstMap, {partialApplyArg},
257-
ParameterConvention::Direct_Guaranteed);
258263
auto pullbackType = vjp->mapTypeIntoContext(
259264
vjp->getConventions().getSILType(
260265
vjp->getLoweredFunctionType()->getResults().back(),
@@ -943,8 +948,9 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() {
943948
// returned pullback's closure context.
944949
auto *origExit = &*original->findReturnBB();
945950
auto pbTupleType =
946-
pullbackInfo.getLinearMapTupleLoweredType(origExit).getASTType();
947-
pbParams.emplace_back(pbTupleType, ParameterConvention::Direct_Owned);
951+
pullbackInfo.getLinearMapTupleLoweredType(origExit).getAs<TupleType>();
952+
for (Type eltTy : pbTupleType->getElementTypes())
953+
pbParams.emplace_back(CanType(eltTy), ParameterConvention::Direct_Owned);
948954
}
949955

950956
// Add pullback results for the requested wrt parameters.
@@ -1014,19 +1020,26 @@ SILBasicBlock *VJPCloner::Implementation::createTrampolineBasicBlock(
10141020
return trampolineBB;
10151021
}
10161022

1023+
llvm::SmallVector<SILValue, 8>
1024+
VJPCloner::Implementation::getPullbackValues(SILBasicBlock *origBB) {
1025+
auto *vjpBB = BBMap[origBB];
1026+
auto bbPullbackValues = pullbackValues[origBB];
1027+
if (!origBB->isEntry()) {
1028+
auto *predEnumArg = vjpBB->getArguments().back();
1029+
bbPullbackValues.insert(bbPullbackValues.begin(), predEnumArg);
1030+
}
1031+
1032+
return bbPullbackValues;
1033+
}
1034+
10171035
TupleInst *
10181036
VJPCloner::Implementation::buildPullbackValueTupleValue(TermInst *termInst) {
10191037
assert(termInst->getFunction() == original);
10201038
auto loc = RegularLocation::getAutoGeneratedLocation();
10211039
auto origBB = termInst->getParent();
1022-
auto *vjpBB = BBMap[origBB];
10231040
auto tupleLoweredTy =
10241041
remapType(pullbackInfo.getLinearMapTupleLoweredType(origBB));
1025-
auto bbPullbackValues = pullbackValues[origBB];
1026-
if (!origBB->isEntry()) {
1027-
auto *predEnumArg = vjpBB->getArguments().back();
1028-
bbPullbackValues.insert(bbPullbackValues.begin(), predEnumArg);
1029-
}
1042+
auto bbPullbackValues = getPullbackValues(origBB);
10301043
return getBuilder().createTuple(loc, tupleLoweredTy, bbPullbackValues);
10311044
}
10321045

test/AutoDiff/SILOptimizer/derivative_sil.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,14 @@ func foo(_ x: Float) -> Float {
6565
// CHECK-SIL: [[ADD_VJP_FN:%.*]] = differentiable_function_extract [vjp] [[ADD_DIFF_FN]]
6666
// CHECK-SIL: [[ADD_RESULT:%.*]] = apply [[ADD_VJP_FN]]([[X]], [[X]], {{.*}})
6767
// CHECK-SIL: ([[ORIG_RES:%.*]], [[ADD_PB:%.*]]) = destructure_tuple [[ADD_RESULT]]
68-
// CHECK-SIL: [[PB_STRUCT:%.*]] = tuple ([[ADD_PB]] : $@callee_guaranteed (Float) -> (Float, Float))
69-
// CHECK-SIL: [[PB_REF:%.*]] = function_ref @fooTJpSpSr : $@convention(thin) (Float, @owned (_: @callee_guaranteed (Float) -> (Float, Float))) -> Float
70-
// CHECK-SIL: [[PB_FN:%.*]] = partial_apply [callee_guaranteed] [[PB_REF]]([[PB_STRUCT]])
68+
// CHECK-SIL: [[PB_REF:%.*]] = function_ref @fooTJpSpSr : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float
69+
// CHECK-SIL: [[PB_FN:%.*]] = partial_apply [callee_guaranteed] [[PB_REF]]([[ADD_PB]])
7170
// CHECK-SIL: [[VJP_RESULT:%.*]] = tuple ([[ORIG_RES]] : $Float, [[PB_FN]] : $@callee_guaranteed (Float) -> Float)
7271
// CHECK-SIL: return [[VJP_RESULT]] : $(Float, @callee_guaranteed (Float) -> Float)
7372
// CHECK-SIL: }
7473

75-
// CHECK-SIL-LABEL: sil private [ossa] @fooTJpSpSr : $@convention(thin) (Float, @owned (_: @callee_guaranteed (Float) -> (Float, Float))) -> Float {
76-
// CHECK-SIL: bb0([[DY:%.*]] : $Float, [[PB_STRUCT:%.*]] : @owned $(_: @callee_guaranteed (Float) -> (Float, Float))):
77-
// CHECK-SIL: [[ADD_PB:%.*]] = destructure_tuple [[PB_STRUCT]] : $(_: @callee_guaranteed (Float) -> (Float, Float))
74+
// CHECK-SIL-LABEL: sil private [ossa] @fooTJpSpSr : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float {
75+
// CHECK-SIL: bb0([[DY:%.*]] : $Float, [[ADD_PB:%.*]] : @owned $@callee_guaranteed (Float) -> (Float, Float)):
7876
// CHECK-SIL: debug_value [[DY]] : $Float, let, name "y"
7977
// CHECK-SIL: [[ADD_PB_RES:%.*]] = apply [[ADD_PB]]([[DY]]) : $@callee_guaranteed (Float) -> (Float, Float)
8078
// CHECK-SIL: ([[DX_1:%.*]], [[DX_2:%.*]]) = destructure_tuple [[ADD_PB_RES]] : $(Float, Float)
@@ -112,4 +110,4 @@ struct ExampleStruct {
112110

113111
// CHECK-SIL-LABEL: sil hidden [ossa] @fooMethodTJrSUpSr : $@convention(method) (Float, ExampleStruct) -> (Float, @owned @callee_guaranteed (Float) -> Float) {
114112

115-
// CHECK-SIL-LABEL: sil private [ossa] @fooMethodTJpSUpSr : $@convention(thin) (Float, @owned (_: @callee_guaranteed (Float) -> (Float, Float))) -> Float {
113+
// CHECK-SIL-LABEL: sil private [ossa] @fooMethodTJpSUpSr : $@convention(thin) (Float, @owned @callee_guaranteed (Float) -> (Float, Float)) -> Float {

test/AutoDiff/SILOptimizer/differentiation_control_flow_sil.swift

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,14 @@ func cond(_ x: Float) -> Float {
5757
// CHECK-SIL: br bb3({{.*}} : $Float, [[BB3_PRED_PRED2]] : $_AD__cond_bb3__Pred__src_0_wrt_0)
5858

5959
// CHECK-SIL: bb3([[ORIG_RES:%.*]] : $Float, [[BB3_PRED_ARG:%.*]] : $_AD__cond_bb3__Pred__src_0_wrt_0)
60-
// CHECK-SIL: [[BB3_PB_STRUCT:%.*]] = tuple $(predecessor: _AD__cond_bb3__Pred__src_0_wrt_0) ([[BB3_PRED_ARG]])
6160
// CHECK-SIL: [[PULLBACK_REF:%.*]] = function_ref @condTJpSpSr
62-
// CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PULLBACK_REF]]([[BB3_PB_STRUCT]])
61+
// CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PULLBACK_REF]]([[BB3_PRED_ARG]])
6362
// CHECK-SIL: [[VJP_RESULT:%.*]] = tuple ([[ORIG_RES]] : $Float, [[PB]] : $@callee_guaranteed (Float) -> Float)
6463
// CHECK-SIL: return [[VJP_RESULT]]
6564

6665

67-
// CHECK-SIL-LABEL: sil private [ossa] @condTJpSpSr : $@convention(thin) (Float, @owned (predecessor: _AD__cond_bb3__Pred__src_0_wrt_0)) -> Float {
68-
// CHECK-SIL: bb0([[SEED:%.*]] : $Float, [[BB3_PB_STRUCT:%.*]] : $(predecessor: _AD__cond_bb3__Pred__src_0_wrt_0)):
69-
// CHECK-SIL: [[BB3_PRED:%.*]] = destructure_tuple [[BB3_PB_STRUCT]] : $(predecessor: _AD__cond_bb3__Pred__src_0_wrt_0)
66+
// CHECK-SIL-LABEL: sil private [ossa] @condTJpSpSr : $@convention(thin) (Float, @owned _AD__cond_bb3__Pred__src_0_wrt_0) -> Float {
67+
// CHECK-SIL: bb0([[SEED:%.*]] : $Float, [[BB3_PRED:%.*]] : $_AD__cond_bb3__Pred__src_0_wrt_0):
7068
// CHECK-SIL: switch_enum [[BB3_PRED]] : $_AD__cond_bb3__Pred__src_0_wrt_0, case #_AD__cond_bb3__Pred__src_0_wrt_0.bb2!enumelt: bb1, case #_AD__cond_bb3__Pred__src_0_wrt_0.bb1!enumelt: bb3
7169

7270
// CHECK-SIL: bb1([[BB3_PRED2_TRAMP_PB_STRUCT:%.*]] : @owned $(predecessor: _AD__cond_bb2__Pred__src_0_wrt_0, @callee_guaranteed (Float) -> (Float, Float))):
@@ -167,9 +165,8 @@ func enum_notactive(_ e: Enum, _ x: Float) -> Float {
167165
// CHECK-SIL: br bb3({{.*}} : $Float, [[BB3_PRED_PRED2]] : $_AD__enum_notactive_bb3__Pred__src_0_wrt_1)
168166

169167
// CHECK-SIL: bb3([[ORIG_RES:%.*]] : $Float, [[BB3_PRED_ARG:%.*]] : $_AD__enum_notactive_bb3__Pred__src_0_wrt_1)
170-
// CHECK-SIL: [[BB3_PB_STRUCT:%.*]] = tuple $(predecessor: _AD__enum_notactive_bb3__Pred__src_0_wrt_1) ([[BB3_PRED_ARG]])
171168
// CHECK-SIL: [[PULLBACK_REF:%.*]] = function_ref @enum_notactiveTJpUSpSr
172-
// CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PULLBACK_REF]]([[BB3_PB_STRUCT]])
169+
// CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PULLBACK_REF]]([[BB3_PRED_ARG]])
173170
// CHECK-SIL: [[VJP_RESULT:%.*]] = tuple ([[ORIG_RES]] : $Float, [[PB]] : $@callee_guaranteed (Float) -> Float)
174171
// CHECK-SIL: return [[VJP_RESULT]]
175172

@@ -214,10 +211,9 @@ func enum_addr_notactive<T>(_ e: AddressOnlyEnum<T>, _ x: Float) -> Float {
214211
// CHECK-SIL: br bb3([[BB3_PRED_PRED2]] : $_AD__enum_addr_notactive_bb3__Pred__src_0_wrt_1_l<τ_0_0>)
215212

216213
// CHECK-SIL: bb3([[BB3_PRED_ARG:%.*]] : $_AD__enum_addr_notactive_bb3__Pred__src_0_wrt_1_l<τ_0_0>):
217-
// CHECK-SIL: [[BB3_PB_STRUCT:%.*]] = tuple $(predecessor: _AD__enum_addr_notactive_bb3__Pred__src_0_wrt_1_l<τ_0_0>) ([[BB3_PRED_ARG]])
218214

219-
// CHECK-SIL: [[PB_FNREF:%.*]] = function_ref @enum_addr_notactivelTJpUSpSr : $@convention(thin) <τ_0_0> (Float, @owned (predecessor: _AD__enum_addr_notactive_bb3__Pred__src_0_wrt_1_l<τ_0_0>)) -> Float
220-
// CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PB_FNREF]]<τ_0_0>([[BB3_PB_STRUCT]]) : $@convention(thin) <τ_0_0> (Float, @owned (predecessor: _AD__enum_addr_notactive_bb3__Pred__src_0_wrt_1_l<τ_0_0>)) -> Float
215+
// CHECK-SIL: [[PB_FNREF:%.*]] = function_ref @enum_addr_notactivelTJpUSpSr : $@convention(thin) <τ_0_0> (Float, @owned _AD__enum_addr_notactive_bb3__Pred__src_0_wrt_1_l<τ_0_0>) -> Float
216+
// CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PB_FNREF]]<τ_0_0>([[BB3_PRED_ARG]]) : $@convention(thin) <τ_0_0> (Float, @owned _AD__enum_addr_notactive_bb3__Pred__src_0_wrt_1_l<τ_0_0>) -> Float
221217
// CHECK-SIL: [[VJP_RESULT:%.*]] = tuple ([[X_ARG]] : $Float, [[PB]] : $@callee_guaranteed (Float) -> Float)
222218
// CHECK-SIL: return [[VJP_RESULT]] : $(Float, @callee_guaranteed (Float) -> Float)
223219

@@ -235,9 +231,8 @@ func cond_tuple_var(_ x: Float) -> Float {
235231
return y.1
236232
}
237233

238-
// CHECK-SIL-LABEL: sil private [ossa] @cond_tuple_varTJpSpSr : $@convention(thin) (Float, @owned (predecessor: _AD__cond_tuple_var_bb3__Pred__src_0_wrt_0)) -> Float {
239-
// CHECK-SIL: bb0([[SEED:%.*]] : $Float, [[BB3_PB_STRUCT:%.*]] : $(predecessor: _AD__cond_tuple_var_bb3__Pred__src_0_wrt_0)):
240-
// CHECK-SIL: [[BB3_PRED:%.*]] = destructure_tuple [[BB3_PB_STRUCT]] : $(predecessor: _AD__cond_tuple_var_bb3__Pred__src_0_wrt_0)
234+
// CHECK-SIL-LABEL: sil private [ossa] @cond_tuple_varTJpSpSr : $@convention(thin) (Float, @owned _AD__cond_tuple_var_bb3__Pred__src_0_wrt_0) -> Float {
235+
// CHECK-SIL: bb0([[SEED:%.*]] : $Float, [[BB3_PRED:%.*]] : $_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0):
241236
// CHECK-SIL: copy_addr {{%.*}} to {{%.*}} : $*(Float, Float)
242237
// CHECK-SIL-NOT: copy_addr {{%.*}} to {{%.*}} : $*Float
243238
// CHECK-SIL: switch_enum [[BB3_PRED]] : $_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0, case #_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0.bb2!enumelt: bb1, case #_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0.bb1!enumelt: bb3

0 commit comments

Comments
 (0)