Skip to content

Commit

Permalink
Fix the hang in the SILBuilder::addOpenedArchetypeOperands
Browse files Browse the repository at this point in the history
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
  • Loading branch information
swiftix committed Sep 24, 2017
1 parent 879c0c6 commit 7f4c4f7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
5 changes: 4 additions & 1 deletion lib/SIL/SILBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,10 +410,13 @@ void SILBuilder::addOpenedArchetypeOperands(SILInstruction *I) {
if (I && I->getNumTypeDependentOperands() > 0)
return;

// Keep track of already visited instructions to avoid infinite loops.
SmallPtrSet<SILInstruction *, 8> Visited;

while (I && I->getNumOperands() == 1 &&
I->getNumTypeDependentOperands() == 0) {
I = dyn_cast<SILInstruction>(I->getOperand(0));
if (!I)
if (!I || !Visited.insert(I).second)
return;
// If it is a definition of an opened archetype,
// register it and exit.
Expand Down
51 changes: 51 additions & 0 deletions test/SILOptimizer/opened_archetype_operands_tracking.sil
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -sil-inline-generics -enable-sil-verify-all %s -O | %FileCheck %s
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -simplify-cfg -enable-sil-verify-all %s -O | %FileCheck --check-prefix=CHECK-SIMPLIFY-CFG %s

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

// Check that even in case of unreacheable blocks the compiler does not hang
// in SILBuilder::addOpenedArchetypeOperands. rdar://problem/34602036

enum MyOptional<T> {
case none
case some(T)
}

class C {
var this : MyOptional<C>
init()
}

// CHECK-SIMPLIFY-CFG-LABEL: sil @test_infinite_loop_in_unreachable_block
// CHECK-SIMPLIFY-CFG: bb0
// CHECK-SIMPLIFY-CFG-NOT: bb1
// CHECK-SIMPLIFY-CFG: end sil function 'test_infinite_loop_in_unreachable_block'
sil @test_infinite_loop_in_unreachable_block : $@convention(method) (@guaranteed C) -> () {
bb0(%0 : $C):
%1 = enum $MyOptional<C>, #MyOptional.some!enumelt.1, %0 : $C
%2 = integer_literal $Builtin.Int64, 0
strong_retain %0 : $C
release_value %1 : $MyOptional<C>
%6 = integer_literal $Builtin.Int1, -1
cond_br %6, bb5, bb1

bb1:
%8 = enum $MyOptional<C>, #MyOptional.some!enumelt.1, %0 : $C
strong_retain %0 : $C
br bb2(%8 : $MyOptional<C>)

bb2(%11 : $MyOptional<C>):
%12 = unchecked_enum_data %11 : $MyOptional<C>, #MyOptional.some!enumelt.1
%13 = ref_element_addr %12 : $C, #C.this
%14 = load %13 : $*MyOptional<C>
switch_enum %14 : $MyOptional<C>, case #MyOptional.some!enumelt.1: bb3, case #MyOptional.none!enumelt: bb4

bb3(%16 : $C):
retain_value %14 : $MyOptional<C>
release_value %11 : $MyOptional<C>
br bb2(%14 : $MyOptional<C>)

bb4:
release_value %11 : $MyOptional<C>
br bb5

bb5:
%22 = tuple ()
return %22 : $()
} // end sil function 'test_infinite_loop_in_unreachable_block'

0 comments on commit 7f4c4f7

Please sign in to comment.