Skip to content

Commit 18c676c

Browse files
committed
Fix SimplifyCFG::simplifySwitchEnumOnObjcClassOptional for OSSA
1 parent 5e759d1 commit 18c676c

File tree

6 files changed

+134
-425
lines changed

6 files changed

+134
-425
lines changed

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,9 @@ bool swift::onlyAffectsRefCount(SILInstruction *user) {
279279
switch (user->getKind()) {
280280
default:
281281
return false;
282-
case SILInstructionKind::AutoreleaseValueInst:
282+
case SILInstructionKind::CopyValueInst:
283283
case SILInstructionKind::DestroyValueInst:
284+
case SILInstructionKind::AutoreleaseValueInst:
284285
case SILInstructionKind::ReleaseValueInst:
285286
case SILInstructionKind::RetainValueInst:
286287
case SILInstructionKind::StrongReleaseInst:

lib/SILOptimizer/Mandatory/DiagnoseInvalidEscapingCaptures.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ static bool checkNoEscapePartialApplyUse(Operand *oper, FollowUse followUses) {
5555
isa<CopyBlockWithoutEscapingInst>(user))
5656
return false;
5757

58+
// Look through copies, borrows, and conversions.
59+
// getSingleValueCopyOrCast handles all result producing instructions for
60+
// which onlyAffectsRefCount returns true.
61+
if (SingleValueInstruction *copy = getSingleValueCopyOrCast(user)) {
62+
// Only follow the copied operand. Other operands are incidental,
63+
// as in the second operand of mark_dependence.
64+
if (oper->getOperandNumber() == 0)
65+
followUses(copy);
66+
67+
return false;
68+
}
69+
5870
// Ignore uses that are totally uninteresting. partial_apply [stack] is
5971
// terminated by a dealloc_stack instruction.
6072
if (isIncidentalUse(user) || onlyAffectsRefCount(user) ||
@@ -69,16 +81,6 @@ static bool checkNoEscapePartialApplyUse(Operand *oper, FollowUse followUses) {
6981
return false;
7082
}
7183

72-
// Look through copies, borrows, and conversions.
73-
if (SingleValueInstruction *copy = getSingleValueCopyOrCast(user)) {
74-
// Only follow the copied operand. Other operands are incidental,
75-
// as in the second operand of mark_dependence.
76-
if (oper->getOperandNumber() == 0)
77-
followUses(copy);
78-
79-
return false;
80-
}
81-
8284
// Look through `differentiable_function`.
8385
if (auto *DFI = dyn_cast<DifferentiableFunctionInst>(user)) {
8486
followUses(DFI);

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,7 +1847,9 @@ static bool containsOnlyObjMethodCallOnOptional(SILValue optionalValue,
18471847

18481848
// The branch should forward one of the objc_method call.
18491849
if (auto *br = dyn_cast<BranchInst>(inst)) {
1850-
if (br->getNumArgs() == 0 || br->getNumArgs() > 1)
1850+
if (br->getNumArgs() == 0)
1851+
continue;
1852+
if (br->getNumArgs() > 1)
18511853
return false;
18521854
auto branchArg = br->getArg(0);
18531855
if (std::find(objCApplies.begin(), objCApplies.end(), branchArg) ==
@@ -1895,6 +1897,9 @@ static bool onlyForwardsNone(SILBasicBlock *noneBB, SILBasicBlock *someBB,
18951897
continue;
18961898
}
18971899
if (auto *noneBranch = dyn_cast<BranchInst>(inst)) {
1900+
if (noneBranch->getNumArgs() == 0) {
1901+
continue;
1902+
}
18981903
if (noneBranch->getNumArgs() != 1 ||
18991904
(noneBranch->getArg(0) != SEI->getOperand() &&
19001905
noneBranch->getArg(0) != optionalNone))
@@ -2006,12 +2011,6 @@ static bool hasSameUltimateSuccessor(SILBasicBlock *noneBB, SILBasicBlock *someB
20062011
/// %4 = enum #Optional.none
20072012
/// br mergeBB(%4)
20082013
bool SimplifyCFG::simplifySwitchEnumOnObjcClassOptional(SwitchEnumInst *SEI) {
2009-
// TODO: OSSA; handle non-trivial enum case cleanup
2010-
// (simplify_switch_enum_objc.sil).
2011-
if (!EnableOSSARewriteTerminator && Fn.hasOwnership()) {
2012-
return false;
2013-
}
2014-
20152014
auto optional = SEI->getOperand();
20162015
auto optionalPayloadType = optional->getType().getOptionalObjectType();
20172016
if (!optionalPayloadType ||
@@ -2048,10 +2047,21 @@ bool SimplifyCFG::simplifySwitchEnumOnObjcClassOptional(SwitchEnumInst *SEI) {
20482047
optionalPayloadType);
20492048
optionalPayload->replaceAllUsesWith(payloadCast);
20502049
auto *switchBB = SEI->getParent();
2051-
if (someBB->getNumArguments())
2052-
Builder.createBranch(SEI->getLoc(), someBB, SILValue(payloadCast));
2053-
else
2050+
2051+
if (!someBB->args_empty()) {
2052+
assert(someBB->getNumArguments() == 1);
2053+
auto *someBBArg = someBB->getArgument(0);
2054+
if (!someBBArg->use_empty()) {
2055+
assert(optionalPayload != someBBArg);
2056+
someBBArg->replaceAllUsesWith(payloadCast);
2057+
}
2058+
someBB->eraseArgument(0);
20542059
Builder.createBranch(SEI->getLoc(), someBB);
2060+
}
2061+
else {
2062+
assert(!Fn.hasOwnership());
2063+
Builder.createBranch(SEI->getLoc(), someBB);
2064+
}
20552065

20562066
SEI->eraseFromParent();
20572067
addToWorklist(switchBB);

lib/SILOptimizer/UtilityPasses/UnitTestRunner.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,19 @@ struct SimplifyCFGSimplifySwitchEnumBlock : UnitTest {
321321
}
322322
};
323323

324+
struct SimplifyCFGSwitchEnumOnObjcClassOptional : UnitTest {
325+
SimplifyCFGSwitchEnumOnObjcClassOptional(UnitTestRunner *pass) : UnitTest(pass) {}
326+
void invoke(Arguments &arguments) override {
327+
auto *passToRun = cast<SILFunctionTransform>(createSimplifyCFG());
328+
passToRun->injectPassManager(getPass()->getPassManager());
329+
passToRun->injectFunction(getFunction());
330+
SimplifyCFG(*getFunction(), *passToRun, /*VerifyAll=*/false,
331+
/*EnableJumpThread=*/false)
332+
.simplifySwitchEnumOnObjcClassOptional(
333+
cast<SwitchEnumInst>(arguments.takeInstruction()));
334+
}
335+
};
336+
324337
struct SimplifyCFGSimplifySwitchEnumUnreachableBlocks : UnitTest {
325338
SimplifyCFGSimplifySwitchEnumUnreachableBlocks(UnitTestRunner *pass)
326339
: UnitTest(pass) {}
@@ -515,6 +528,9 @@ void UnitTestRunner::withTest(StringRef name, Doit doit) {
515528
ADD_UNIT_TEST_SUBCLASS(
516529
"simplify-cfg-simplify-switch-enum-unreachable-blocks",
517530
SimplifyCFGSimplifySwitchEnumUnreachableBlocks)
531+
ADD_UNIT_TEST_SUBCLASS(
532+
"simplify-cfg-simplify-switch-enum-on-objc-class-optional",
533+
SimplifyCFGSwitchEnumOnObjcClassOptional)
518534
ADD_UNIT_TEST_SUBCLASS(
519535
"simplify-cfg-simplify-term-with-identical-dest-blocks",
520536
SimplifyCFGSimplifyTermWithIdenticalDestBlocks)

test/SILOptimizer/outliner.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ public func testOutlining() {
6363
// CHECK: [[OBJ:%.*]] = open_existential_ref {{.*}} : $AnyObject to $@opened("{{.*}}", AnyObject) Self
6464
// CHECK: [[METH:%.*]] = objc_method [[OBJ]] : $@opened("{{.*}}", AnyObject) Self, #Treeish.treeishChildren!foreign : <Self where Self : Treeish> (Self) -> () -> [Any]?
6565
// CHECK: [[RES:%.*]] = apply [[METH]]([[OBJ]]) : $@convention(objc_method)
66-
// CHECK: switch_enum [[RES]]
6766
// CHECK: } // end sil function '$s8outliner9dontCrash1ayyp_tF'
6867

6968
// CHECK-LABEL: sil shared [noinline] @$sSo5GizmoC14stringPropertySSSgvgToTeab_ : {{.*}} {

0 commit comments

Comments
 (0)