Skip to content

Commit a1bb9f4

Browse files
committed
Fix SILVerifier and AddressUtils handling of addr casts.
These core utils did not handle UnconditionalCheckedCastAddrInst or UncheckedRefCastAddrInst correctly.
1 parent 826515f commit a1bb9f4

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/AddressUtils.swift

-1
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

+3-1
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

+17
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.
@@ -685,6 +696,12 @@ struct ImmutableAddressUseVerifier {
685696
}
686697
return true;
687698
}
699+
case SILInstructionKind::UnconditionalCheckedCastAddrInst:
700+
case SILInstructionKind::UncheckedRefCastAddrInst:
701+
if (isConsumingOrMutatingMoveAddrUse(use)) {
702+
return true;
703+
}
704+
break;
688705
case SILInstructionKind::CheckedCastAddrBranchInst:
689706
switch (cast<CheckedCastAddrBranchInst>(inst)->getConsumptionKind()) {
690707
case CastConsumptionKind::BorrowAlways:

test/SILOptimizer/ownership_liveness_unit.sil

+38
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)