Skip to content

Commit 5624365

Browse files
authored
Merge pull request #27424 from gottesmm/swift-5.1-branch-rdar55709778
[simplify-cfg] When determining/searching for the end of a switch_enu…
2 parents 6146333 + e172dc9 commit 5624365

File tree

2 files changed

+70
-6
lines changed

2 files changed

+70
-6
lines changed

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,14 +1878,38 @@ static bool onlyForwardsNone(SILBasicBlock *noneBB, SILBasicBlock *someBB,
18781878
/// \ ... (more bbs?)
18791879
/// \ /
18801880
/// ulimateBB
1881-
static bool hasSameUlitmateSuccessor(SILBasicBlock *noneBB, SILBasicBlock *someBB) {
1881+
static bool hasSameUltimateSuccessor(SILBasicBlock *noneBB, SILBasicBlock *someBB) {
1882+
// Make sure that both our some, none blocks both have single successors that
1883+
// are not themselves (which can happen due to single block loops).
18821884
auto *someSuccessorBB = someBB->getSingleSuccessorBlock();
1883-
if (!someSuccessorBB)
1885+
if (!someSuccessorBB || someSuccessorBB == someBB)
18841886
return false;
18851887
auto *noneSuccessorBB = noneBB->getSingleSuccessorBlock();
1886-
while (noneSuccessorBB != nullptr && noneSuccessorBB != someSuccessorBB)
1887-
noneSuccessorBB = noneSuccessorBB->getSingleSuccessorBlock();
1888-
return noneSuccessorBB == someSuccessorBB;
1888+
if (!noneSuccessorBB || noneSuccessorBB == noneBB)
1889+
return false;
1890+
1891+
// If we immediately find a diamond, return true. We are done.
1892+
if (noneSuccessorBB == someSuccessorBB)
1893+
return true;
1894+
1895+
// Otherwise, lets keep looking down the none case.
1896+
auto *next = noneSuccessorBB;
1897+
while (next != someSuccessorBB) {
1898+
noneSuccessorBB = next;
1899+
next = noneSuccessorBB->getSingleSuccessorBlock();
1900+
1901+
// If we find another single successor and it is not our own block (due to a
1902+
// self-loop), continue.
1903+
if (next && next != noneSuccessorBB)
1904+
continue;
1905+
1906+
// Otherwise, we either have multiple successors or a self-loop. We do not
1907+
// support this, return false.
1908+
return false;
1909+
}
1910+
1911+
// At this point, we know that next must be someSuccessorBB.
1912+
return true;
18891913
}
18901914

18911915
/// Simplify switch_enums on class enums that branch to objc_method calls on
@@ -1920,7 +1944,7 @@ bool SimplifyCFG::simplifySwitchEnumOnObjcClassOptional(SwitchEnumInst *SEI) {
19201944
if (SEI->getCaseDestination(someDecl) != someBB)
19211945
std::swap(someBB, noneBB);
19221946

1923-
if (!hasSameUlitmateSuccessor(noneBB, someBB))
1947+
if (!hasSameUltimateSuccessor(noneBB, someBB))
19241948
return false;
19251949

19261950
if (!onlyForwardsNone(noneBB, someBB, SEI))

test/SILOptimizer/simplify_switch_enum_objc.sil

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,43 @@ bb8:
381381
bb9:
382382
br bb7
383383
}
384+
385+
sil @infinite_loop_get_optional_nsobject : $@convention(thin) () -> @autoreleased Optional<NSObject>
386+
sil @infinite_loop_get_superview : $@convention(thin) (NSObject) -> @autoreleased Optional<NSObject>
387+
388+
// Just make sure we do not infinite loop here when looking for successors.
389+
// CHECK-LABEL: sil @infinite_loop_1 : $@convention(thin) () -> @owned Optional<NSObject> {
390+
// CHECK: } // end sil function 'infinite_loop_1'
391+
sil @infinite_loop_1 : $@convention(thin) () -> @owned Optional<NSObject> {
392+
bb0:
393+
%13 = function_ref @infinite_loop_get_optional_nsobject : $@convention(thin) () -> @autoreleased Optional<NSObject>
394+
%14 = apply %13() : $@convention(thin) () -> @autoreleased Optional<NSObject>
395+
br bb1(%14 : $Optional<NSObject>)
396+
397+
bb1(%16 : $Optional<NSObject>):
398+
retain_value %16 : $Optional<NSObject>
399+
switch_enum %16 : $Optional<NSObject>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5
400+
401+
bb2(%19 : $NSObject):
402+
release_value %16 : $Optional<NSObject>
403+
%21 = enum $Optional<NSObject>, #Optional.none!enumelt
404+
release_value %16 : $Optional<NSObject>
405+
return %21 : $Optional<NSObject>
406+
407+
bb3:
408+
%24 = unchecked_enum_data %16 : $Optional<NSObject>, #Optional.some!enumelt.1
409+
strong_retain %24 : $NSObject
410+
%26 = function_ref @infinite_loop_get_superview : $@convention(thin) (NSObject) -> @autoreleased Optional<NSObject>
411+
%27 = apply %26(%24) : $@convention(thin) (NSObject) -> @autoreleased Optional<NSObject>
412+
strong_release %24 : $NSObject
413+
release_value %16 : $Optional<NSObject>
414+
br bb1(%27 : $Optional<NSObject>)
415+
416+
bb4:
417+
release_value %16 : $Optional<NSObject>
418+
br bb1(%16 : $Optional<NSObject>)
419+
420+
bb5:
421+
release_value %16 : $Optional<NSObject>
422+
switch_enum %16 : $Optional<NSObject>, case #Optional.none!enumelt: bb4, default bb3
423+
}

0 commit comments

Comments
 (0)