Skip to content

Commit 73a2819

Browse files
Merge pull request #74836 from nate-chandler/cherrypick/release/6.0/rdar130427564_2
6.0: [PrunedLiveness] Branch summary merges to ending.
2 parents 8349b41 + 3c74824 commit 73a2819

File tree

7 files changed

+130
-5
lines changed

7 files changed

+130
-5
lines changed

include/swift/SIL/PrunedLiveness.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ class PrunedLiveness {
399399
: value(lifetimeEnding ? Value::Ending : Value::NonEnding) {}
400400
operator Value() const { return value; }
401401
LifetimeEnding meet(LifetimeEnding const other) const {
402-
return value < other.value ? *this : other;
402+
return std::min(value, other.value);
403403
}
404404
void meetInPlace(LifetimeEnding const other) { *this = meet(other); }
405405
bool isEnding() const { return value == Value::Ending; }

lib/SIL/Utils/PrunedLiveness.cpp

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,43 @@ static FunctionTest
192192
// PrunedLiveRange
193193
//===----------------------------------------------------------------------===//
194194

195+
static PrunedLiveness::LifetimeEnding
196+
branchMeet(PrunedLiveness::LifetimeEnding const lhs,
197+
PrunedLiveness::LifetimeEnding const rhs) {
198+
enum BranchLifetimeEnding {
199+
Ending,
200+
NonEnding,
201+
NonUse,
202+
};
203+
auto toBranch =
204+
[](PrunedLiveness::LifetimeEnding const ending) -> BranchLifetimeEnding {
205+
switch (ending) {
206+
case PrunedLiveness::LifetimeEnding::Value::NonEnding:
207+
return NonEnding;
208+
case PrunedLiveness::LifetimeEnding::Value::Ending:
209+
return Ending;
210+
case PrunedLiveness::LifetimeEnding::Value::NonUse:
211+
return NonUse;
212+
}
213+
};
214+
auto toRegular =
215+
[](BranchLifetimeEnding const ending) -> PrunedLiveness::LifetimeEnding {
216+
switch (ending) {
217+
case NonEnding:
218+
return PrunedLiveness::LifetimeEnding::Value::NonEnding;
219+
case Ending:
220+
return PrunedLiveness::LifetimeEnding::Value::Ending;
221+
case NonUse:
222+
return PrunedLiveness::LifetimeEnding::Value::NonUse;
223+
}
224+
};
225+
return toRegular(std::min(toBranch(lhs), toBranch(rhs)));
226+
}
227+
static void branchMeetInPlace(PrunedLiveness::LifetimeEnding &that,
228+
PrunedLiveness::LifetimeEnding const other) {
229+
that = branchMeet(that, other);
230+
}
231+
195232
template <typename LivenessWithDefs>
196233
void PrunedLiveRange<LivenessWithDefs>::updateForUse(
197234
SILInstruction *user,
@@ -210,8 +247,13 @@ void PrunedLiveRange<LivenessWithDefs>::updateForUse(
210247
// This call is not considered the end of %val's lifetime. The @owned
211248
// argument must be copied.
212249
auto iterAndSuccess = users.insert({user, lifetimeEnding});
213-
if (!iterAndSuccess.second)
214-
iterAndSuccess.first->second.meetInPlace(lifetimeEnding);
250+
if (!iterAndSuccess.second) {
251+
if (isa<BranchInst>(user)) {
252+
branchMeetInPlace(iterAndSuccess.first->second, lifetimeEnding);
253+
} else {
254+
iterAndSuccess.first->second.meetInPlace(lifetimeEnding);
255+
}
256+
}
215257
}
216258
template <typename LivenessWithDefs>
217259
void PrunedLiveRange<LivenessWithDefs>::updateForUse(SILInstruction *user,

lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,15 @@ void MoveOnlyChecker::completeObjectLifetimes(
169169
}
170170
}
171171
}
172+
for (SILArgument *arg : block->getArguments()) {
173+
assert(!arg->isReborrow() && "reborrows not legal at this SIL stage");
174+
if (!transitiveValues.isVisited(arg))
175+
continue;
176+
if (completion.completeOSSALifetime(arg) ==
177+
LifetimeCompletion::WasCompleted) {
178+
madeChange = true;
179+
}
180+
}
172181
}
173182
}
174183

test/SILOptimizer/liveness_unit.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ bb1(%reborrow : @guaranteed $C, %phi : @guaranteed $PairC):
378378
// CHECK-LABEL: testSSAReborrowedPhi: ssa_liveness
379379
// CHECK: SSA lifetime analysis: %{{.*}} = begin_borrow
380380
// CHECK-NEXT: bb0: LiveWithin
381-
// CHECK-NEXT: regular user: br bb1
381+
// CHECK-NEXT: lifetime-ending user: br bb1
382382
// CHECK-NEXT: regular user: %{{.*}} = struct
383383
// CHECK-NEXT: last user: br bb1
384384
// CHECK-NEXT: end running

test/SILOptimizer/moveonly_addresschecker_unmaximized.sil

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ struct M4: ~Copyable {
2121
let s4: M
2222
}
2323

24+
class C {}
25+
2426
sil @get_M4 : $@convention(thin) () -> @owned M4
2527
sil @end_2 : $@convention(thin) (@owned M, @owned M) -> ()
2628
sil @see_addr : $@convention(thin) (@in_guaranteed M) -> ()
2729
sil @see_addr_2 : $@convention(thin) (@in_guaranteed M, @in_guaranteed M) -> ()
2830
sil @replace_2 : $@convention(thin) (@inout M, @inout M) -> ()
2931
sil @get_out_2 : $@convention(thin) () -> (@out M, @out M)
3032
sil @take_addr_2 : $@convention(thin) (@in M, @in M) -> ()
33+
sil @getC : $@convention(thin) () -> (@owned C)
3134

3235
/// Two non-contiguous fields (#M4.s2, #M4.s4) are borrowed by @see_addr_2.
3336
/// Two non-contiguous fields (#M4.s1, #M$.s3) are consumed by @end_2.
@@ -253,3 +256,37 @@ bb0(%0 : @guaranteed $M):
253256
return %retval : $()
254257
}
255258

259+
// CHECK-LABEL: sil [ossa] @rdar130427564 : {{.*}} {
260+
// Verify that no instructions were inserted after backedge2's terminator. (In
261+
// fact, if they were, the test would crash.)
262+
// CHECK: bb2([[C0:%[^,]+]] : @owned $C, [[B0:%[^,]+]] : @reborrow @guaranteed $C):
263+
// CHECK-NEXT: end_borrow [[B0]]
264+
// CHECK-NEXT: destroy_value [[C0]]
265+
// CHECK-NEXT: br
266+
// CHECK-LABEL: } // end sil function 'rdar130427564'
267+
sil [ossa] @rdar130427564 : $@convention(thin) (@in_guaranteed M) -> () {
268+
entry(%ignore_me : $*M):
269+
%ignore_me_2 = mark_unresolved_non_copyable_value [no_consume_or_assign] %ignore_me : $*M
270+
br fn
271+
fn:
272+
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
273+
%c = apply %getC() : $@convention(thin) () -> (@owned C)
274+
%b = begin_borrow %c : $C
275+
br header(%c : $C, %b : $C)
276+
header(%c0 : @owned $C, %b0 : @reborrow @guaranteed $C):
277+
end_borrow %b0 : $C
278+
destroy_value %c0 : $C
279+
br body
280+
body:
281+
br latch
282+
latch:
283+
cond_br undef, backedge, ecit
284+
backedge:
285+
%c1 = apply %getC() : $@convention(thin) () -> (@owned C)
286+
%b1 = begin_borrow %c1 : $C
287+
br backedge2(%c1 : $C, %b1 : $C)
288+
backedge2(%c2 : @owned $C, %b2 : @reborrow @guaranteed $C):
289+
br header(%c2 : $C, %b2 : $C)
290+
ecit:
291+
unreachable
292+
}

test/SILOptimizer/ossa_lifetime_completion.sil

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public enum FakeOptional<T> {
1111
case some(T)
1212
}
1313

14+
sil @getC : $@convention(thin) () -> (@owned C)
15+
1416
// CHECK-LABEL: begin running test 1 of 1 on eagerConsumneOwnedArg: ossa-lifetime-completion with: @argument
1517
// CHECK-LABEL: OSSA lifetime completion: %0 = argument of bb0 : $C
1618
// CHECK: sil [ossa] @eagerConsumneOwnedArg : $@convention(thin) (@owned C) -> () {
@@ -395,3 +397,38 @@ exit:
395397
%retval = tuple ()
396398
return %retval : $()
397399
}
400+
401+
// CHECK-LABEL: begin running test {{.*}} on root_of_reborrow: ossa-lifetime-completion
402+
// Verify that no instructions were inserted after backedge2's terminator. (In
403+
// fact, if they were, the test would crash.)
404+
// CHECK-LABEL: sil [ossa] @root_of_reborrow : {{.*}} {
405+
// CHECK: bb1([[C0:%[^,]+]] : @owned $C, [[B0:%[^,]+]] : @reborrow @guaranteed $C):
406+
// CHECK-NEXT: end_borrow [[B0]]
407+
// CHECK-NEXT: destroy_value [[C0]]
408+
// CHECK-NEXT: br
409+
// CHECK-LABEL: } // end sil function 'root_of_reborrow'
410+
// CHECK-LABEL: end running test {{.*}} on root_of_reborrow: ossa-lifetime-completion
411+
sil [ossa] @root_of_reborrow : $@convention(thin) () -> () {
412+
entry:
413+
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
414+
%c = apply %getC() : $@convention(thin) () -> (@owned C)
415+
%b = begin_borrow %c : $C
416+
br header(%c : $C, %b : $C)
417+
header(%c0 : @owned $C, %b0 : @reborrow @guaranteed $C):
418+
end_borrow %b0 : $C
419+
destroy_value %c0 : $C
420+
br body
421+
body:
422+
br latch
423+
latch:
424+
cond_br undef, backedge, exit
425+
backedge:
426+
%c1 = apply %getC() : $@convention(thin) () -> (@owned C)
427+
%b1 = begin_borrow %c1 : $C
428+
br backedge2(%c1 : $C, %b1 : $C)
429+
backedge2(%c2 : @owned $C, %b2 : @reborrow @guaranteed $C):
430+
specify_test "ossa-lifetime-completion %c2"
431+
br header(%c2 : $C, %b2 : $C)
432+
exit:
433+
unreachable
434+
}

test/SILOptimizer/ownership_liveness_unit.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ bb1(%reborrow : @guaranteed $C):
386386
// CHECK: Interior liveness: %{{.*}} = begin_borrow %0 : $C
387387
// CHECK-NEXT: Inner scope: %{{.*}} = begin_borrow %{{.*}} : $D
388388
// CHECK-NEXT: bb0: LiveWithin
389-
// CHECK-NEXT: regular user: br bb1(%{{.*}} : $C, %{{.*}} : $D)
389+
// CHECK-NEXT: lifetime-ending user: br bb1(%{{.*}} : $C, %{{.*}} : $D)
390390
// CHECK-NEXT: regular user: %{{.*}} = unchecked_ref_cast %{{.*}} : $C to $D
391391
// CHECK-NEXT: Complete liveness
392392
// CHECK-NEXT: Unenclosed phis {

0 commit comments

Comments
 (0)