Skip to content

Commit 05790dc

Browse files
committed
Fix SILVerifier and AddressUtils handling of addr casts.
These core utils did not handle UnconditionalCheckedCastAddrInst or UncheckedRefCastAddrInst correctly. (cherry picked from commit a1bb9f4)
1 parent b099cd5 commit 05790dc

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/AddressUtils.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ extension AddressUseVisitor {
127127
is InitEnumDataAddrInst, is UncheckedTakeEnumDataAddrInst,
128128
is InitExistentialAddrInst, is OpenExistentialAddrInst,
129129
is ProjectBlockStorageInst, is UncheckedAddrCastInst,
130-
is UnconditionalCheckedCastAddrInst,
131130
is MarkUninitializedInst, is DropDeinitInst,
132131
is CopyableToMoveOnlyWrapperAddrInst,
133132
is MoveOnlyWrapperToCopyableAddrInst,

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,9 @@ final public class DebugStepInst : Instruction {}
432432

433433
final public class SpecifyTestInst : Instruction {}
434434

435-
final public class UnconditionalCheckedCastAddrInst : Instruction {
435+
final public class UnconditionalCheckedCastAddrInst : Instruction, SourceDestAddrInstruction {
436+
public var isTakeOfSrc: Bool { true }
437+
public var isInitializationOfDest: Bool { true }
436438
public override var mayTrap: Bool { true }
437439
}
438440

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,17 @@ struct ImmutableAddressUseVerifier {
556556
return false;
557557
}
558558

559+
/// Handle instructions that move a value from one address into another
560+
/// address.
561+
bool isConsumingOrMutatingMoveAddrUse(Operand *use) {
562+
assert(use->getUser()->getNumOperands() == 2);
563+
auto opIdx = use->getOperandNumber();
564+
if (opIdx == CopyLikeInstruction::Dest)
565+
return true;
566+
assert(opIdx == CopyLikeInstruction::Src);
567+
return false;
568+
}
569+
559570
bool isAddrCastToNonConsuming(SingleValueInstruction *i) {
560571
// Check if any of our uses are consuming. If none of them are consuming, we
561572
// are good to go.
@@ -679,6 +690,12 @@ struct ImmutableAddressUseVerifier {
679690
}
680691
return true;
681692
}
693+
case SILInstructionKind::UnconditionalCheckedCastAddrInst:
694+
case SILInstructionKind::UncheckedRefCastAddrInst:
695+
if (isConsumingOrMutatingMoveAddrUse(use)) {
696+
return true;
697+
}
698+
break;
682699
case SILInstructionKind::CheckedCastAddrBranchInst:
683700
switch (cast<CheckedCastAddrBranchInst>(inst)->getConsumptionKind()) {
684701
case CastConsumptionKind::BorrowAlways:

test/SILOptimizer/ownership_liveness_unit.sil

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,44 @@ bb0(%0 : @guaranteed $C):
274274
return %99 : $()
275275
}
276276

277+
// CHECK-LABEL: testInteriorUnconditionalAddrCast: interior-liveness with: %1
278+
// CHECK: Interior liveness: %1 = argument of bb0 : $D
279+
// CHECK-NEXT: bb0: LiveWithin
280+
// CHECK-NEXT: regular user: [[FIELD:%.*]] = ref_element_addr %1 : $D, #D.object
281+
// CHECK-NEXT: regular user: unconditional_checked_cast_addr C in [[FIELD]] : $*C to D in %0 : $*D
282+
// CHECK-NEXT: regular user: copy_addr [take] %4 to [init] [[FIELD]] : $*C
283+
// CHECK-NEXT: regular user: unchecked_ref_cast_addr C in [[FIELD]] : $*C to D in %0 : $*D
284+
// CHECK-NEXT: Complete liveness
285+
// CHECK-NEXT: Unenclosed phis {
286+
// CHECK-NEXT: }
287+
// CHECK-NEXT: last user: unchecked_ref_cast_addr C in [[FIELD]] : $*C to D in %0 : $*D
288+
// CHECK-NEXT: testInteriorUnconditionalAddrCast: interior-liveness with: %1
289+
290+
// CHECK-LABEL: testInteriorUnconditionalAddrCast: interior_liveness_swift with: %1
291+
// CHECK: Interior liveness: %1 = argument of bb0 : $D
292+
// CHECK-NEXT: begin: [[FIELD]] = ref_element_addr %1 : $D, #D.object
293+
// CHECK-NEXT: ends: unchecked_ref_cast_addr C in [[FIELD]] : $*C to D in %0 : $*D
294+
// CHECK-NEXT: exits:
295+
// CHECK-NEXT: interiors: copy_addr [take] %4 to [init] [[FIELD]] : $*C
296+
// CHECK-NEXT: unconditional_checked_cast_addr C in [[FIELD]] : $*C to D in %0 : $*D
297+
// CHECK-NEXT: [[FIELD]] = ref_element_addr %1 : $D, #D.object
298+
// CHECK-NEXT: Unenclosed phis {
299+
// CHECK-NEXT: }
300+
// CHECK-NEXT: last user: unchecked_ref_cast_addr C in [[FIELD]] : $*C to D in %0 : $*D
301+
// CHECK-NEXT: testInteriorUnconditionalAddrCast: interior_liveness_swift with: %1
302+
sil [ossa] @testInteriorUnconditionalAddrCast : $@convention(thin) (@guaranteed D) -> @out D {
303+
bb0(%0 : $*D, %1 : @guaranteed $D):
304+
specify_test "interior-liveness %1"
305+
specify_test "interior_liveness_swift %1"
306+
%c1 = ref_element_addr %1 : $D, #D.object
307+
unconditional_checked_cast_addr C in %c1 : $*C to D in %0 : $*D
308+
%c2 = unchecked_addr_cast %0 : $*D to $*C
309+
copy_addr [take] %c2 to [init] %c1 : $*C
310+
unchecked_ref_cast_addr C in %c1 : $*C to D in %0 : $*D
311+
%99 = tuple()
312+
return %99 : $()
313+
}
314+
277315
// CHECK-LABEL: testInteriorReborrow: interior-liveness with: %borrow
278316
// CHECK: Complete liveness
279317
// CHECK-NEXT: Unenclosed phis {

0 commit comments

Comments
 (0)