Skip to content

Commit 7f4c4f7

Browse files
committed
Fix the hang in the SILBuilder::addOpenedArchetypeOperands
The problem is that within SimplifyCFG we call this for an instruction within unreachable code. And within an unreachable block it can happen that defs do not dominate uses (because there is no dominance defined). The fix is to prevent the infinite loop in addOpenedArchetypeOperands by marking visited instructions. Fixes rdar://problem/34602036
1 parent 879c0c6 commit 7f4c4f7

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

lib/SIL/SILBuilder.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,13 @@ void SILBuilder::addOpenedArchetypeOperands(SILInstruction *I) {
410410
if (I && I->getNumTypeDependentOperands() > 0)
411411
return;
412412

413+
// Keep track of already visited instructions to avoid infinite loops.
414+
SmallPtrSet<SILInstruction *, 8> Visited;
415+
413416
while (I && I->getNumOperands() == 1 &&
414417
I->getNumTypeDependentOperands() == 0) {
415418
I = dyn_cast<SILInstruction>(I->getOperand(0));
416-
if (!I)
419+
if (!I || !Visited.insert(I).second)
417420
return;
418421
// If it is a definition of an opened archetype,
419422
// register it and exit.

test/SILOptimizer/opened_archetype_operands_tracking.sil

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -sil-inline-generics -enable-sil-verify-all %s -O | %FileCheck %s
2+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -simplify-cfg -enable-sil-verify-all %s -O | %FileCheck --check-prefix=CHECK-SIMPLIFY-CFG %s
23

34
// Check some corner cases related to tracking of opened archetypes.
45
// For example, the compiler used to crash compiling the "process" function (rdar://28024272)
@@ -262,3 +263,53 @@ bb0(%0 : $AnyObject):
262263
return %8 : $()
263264
} // end sil function 'check_removal_of_unregistered_archetype_def'
264265

266+
// Check that even in case of unreacheable blocks the compiler does not hang
267+
// in SILBuilder::addOpenedArchetypeOperands. rdar://problem/34602036
268+
269+
enum MyOptional<T> {
270+
case none
271+
case some(T)
272+
}
273+
274+
class C {
275+
var this : MyOptional<C>
276+
init()
277+
}
278+
279+
// CHECK-SIMPLIFY-CFG-LABEL: sil @test_infinite_loop_in_unreachable_block
280+
// CHECK-SIMPLIFY-CFG: bb0
281+
// CHECK-SIMPLIFY-CFG-NOT: bb1
282+
// CHECK-SIMPLIFY-CFG: end sil function 'test_infinite_loop_in_unreachable_block'
283+
sil @test_infinite_loop_in_unreachable_block : $@convention(method) (@guaranteed C) -> () {
284+
bb0(%0 : $C):
285+
%1 = enum $MyOptional<C>, #MyOptional.some!enumelt.1, %0 : $C
286+
%2 = integer_literal $Builtin.Int64, 0
287+
strong_retain %0 : $C
288+
release_value %1 : $MyOptional<C>
289+
%6 = integer_literal $Builtin.Int1, -1
290+
cond_br %6, bb5, bb1
291+
292+
bb1:
293+
%8 = enum $MyOptional<C>, #MyOptional.some!enumelt.1, %0 : $C
294+
strong_retain %0 : $C
295+
br bb2(%8 : $MyOptional<C>)
296+
297+
bb2(%11 : $MyOptional<C>):
298+
%12 = unchecked_enum_data %11 : $MyOptional<C>, #MyOptional.some!enumelt.1
299+
%13 = ref_element_addr %12 : $C, #C.this
300+
%14 = load %13 : $*MyOptional<C>
301+
switch_enum %14 : $MyOptional<C>, case #MyOptional.some!enumelt.1: bb3, case #MyOptional.none!enumelt: bb4
302+
303+
bb3(%16 : $C):
304+
retain_value %14 : $MyOptional<C>
305+
release_value %11 : $MyOptional<C>
306+
br bb2(%14 : $MyOptional<C>)
307+
308+
bb4:
309+
release_value %11 : $MyOptional<C>
310+
br bb5
311+
312+
bb5:
313+
%22 = tuple ()
314+
return %22 : $()
315+
} // end sil function 'test_infinite_loop_in_unreachable_block'

0 commit comments

Comments
 (0)