Skip to content

Commit e9dca65

Browse files
committed
Serialize SIL basic blocks in the RPOT order
Serialize SIL basic blocks in the RPOT order to make sure that instructions defining open archetypes are serialized before instructions using those opened archetypes.
1 parent ae8b2ba commit e9dca65

File tree

4 files changed

+32
-17
lines changed

4 files changed

+32
-17
lines changed

lib/Serialization/SerializeSIL.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
#include "Serialization.h"
1616
#include "swift/Strings.h"
1717
#include "swift/AST/Module.h"
18+
#include "swift/SIL/CFG.h"
1819
#include "swift/SIL/SILArgument.h"
1920
#include "swift/SIL/SILModule.h"
2021
#include "swift/SIL/SILUndef.h"
2122
#include "swift/SILOptimizer/Utils/Generics.h"
2223

2324
#include "llvm/ADT/MapVector.h"
25+
#include "llvm/ADT/PostOrderIterator.h"
2426
#include "llvm/ADT/SmallString.h"
2527
#include "llvm/ADT/SmallVector.h"
2628
#include "llvm/ADT/StringExtras.h"
@@ -390,7 +392,10 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
390392
// Assign a value ID to each SILInstruction that has value and to each basic
391393
// block argument.
392394
unsigned ValueID = 0;
393-
for (const SILBasicBlock &BB : F) {
395+
llvm::ReversePostOrderTraversal<SILFunction *> RPOT(
396+
const_cast<SILFunction *>(&F));
397+
for (auto Iter = RPOT.begin(), E = RPOT.end(); Iter != E; ++Iter) {
398+
auto &BB = **Iter;
394399
BasicBlockMap.insert(std::make_pair(&BB, BasicID++));
395400

396401
for (auto I = BB.bbarg_begin(), E = BB.bbarg_end(); I != E; ++I)
@@ -401,8 +406,17 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
401406
ValueIDs[&SI] = ++ValueID;
402407
}
403408

404-
for (const SILBasicBlock &BB : F)
405-
writeSILBasicBlock(BB);
409+
// Write SIL basic blocks in the RPOT order
410+
// to make sure that instructions defining open archetypes
411+
// are serialized before instructions using those opened
412+
// archetypes.
413+
unsigned SerializedBBNum = 0;
414+
for (auto Iter = RPOT.begin(), E = RPOT.end(); Iter != E; ++Iter) {
415+
auto *BB = *Iter;
416+
writeSILBasicBlock(*BB);
417+
SerializedBBNum++;
418+
}
419+
assert(BasicID == SerializedBBNum && "Wrong number of BBs was serialized");
406420
}
407421

408422
void SILSerializer::writeSILBasicBlock(const SILBasicBlock &BB) {

test/ClangModules/serialization-sil.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,36 @@ public func testPartialApply(_ obj: Test) {
1010
// CHECK-LABEL: @_TF4Test16testPartialApplyFPSo4Test_T_ : $@convention(thin) (@owned Test) -> () {
1111
if let curried1 = obj.normalObject {
1212
// CHECK: dynamic_method_br [[CURRIED1_OBJ:%.+]] : $@opened([[CURRIED1_EXISTENTIAL:.+]]) Test, #Test.normalObject!1.foreign, [[CURRIED1_TRUE:[^,]+]], [[CURRIED1_FALSE:[^,]+]]
13+
// CHECK: [[CURRIED1_FALSE]]:
1314
// CHECK: [[CURRIED1_TRUE]]([[CURRIED1_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject):
1415
// CHECK: [[CURRIED1_PARTIAL:%.+]] = partial_apply [[CURRIED1_METHOD]]([[CURRIED1_OBJ]]) : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject
1516
// CHECK: [[CURRIED1_THUNK:%.+]] = function_ref @_TTRXFo__oPs9AnyObject__XFo_iT__iPS___ : $@convention(thin) (@in (), @owned @callee_owned () -> @owned AnyObject) -> @out AnyObject
1617
// CHECK: = partial_apply [[CURRIED1_THUNK]]([[CURRIED1_PARTIAL]]) : $@convention(thin) (@in (), @owned @callee_owned () -> @owned AnyObject) -> @out AnyObject
17-
// CHECK: [[CURRIED1_FALSE]]:
1818
curried1()
1919
}
2020
if let curried2 = obj.innerPointer {
2121
// CHECK: dynamic_method_br [[CURRIED2_OBJ:%.+]] : $@opened([[CURRIED2_EXISTENTIAL:.+]]) Test, #Test.innerPointer!1.foreign, [[CURRIED2_TRUE:[^,]+]], [[CURRIED2_FALSE:[^,]+]]
22+
// CHECK: [[CURRIED2_FALSE]]:
2223
// CHECK: [[CURRIED2_TRUE]]([[CURRIED2_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutablePointer<()>):
2324
// CHECK: [[CURRIED2_PARTIAL:%.+]] = partial_apply [[CURRIED2_METHOD]]([[CURRIED2_OBJ]]) : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutablePointer<()>
2425
// CHECK: [[CURRIED2_THUNK:%.+]] = function_ref @_TTRXFo__dGSpT___XFo_iT__iGSpT___ : $@convention(thin) (@in (), @owned @callee_owned () -> UnsafeMutablePointer<()>) -> @out UnsafeMutablePointer<()>
2526
// CHECK: = partial_apply [[CURRIED2_THUNK]]([[CURRIED2_PARTIAL]]) : $@convention(thin) (@in (), @owned @callee_owned () -> UnsafeMutablePointer<()>) -> @out UnsafeMutablePointer<()>
26-
// CHECK: [[CURRIED2_FALSE]]:
2727
curried2()
2828
}
2929
if let prop1 = obj.normalObjectProp {
3030
// CHECK: dynamic_method_br [[PROP1_OBJ:%.+]] : $@opened([[PROP1_EXISTENTIAL:.+]]) Test, #Test.normalObjectProp!getter.1.foreign, [[PROP1_TRUE:[^,]+]], [[PROP1_FALSE:[^,]+]]
31+
// CHECK: [[PROP1_FALSE]]:
3132
// CHECK: [[PROP1_TRUE]]([[PROP1_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject):
3233
// CHECK: [[PROP1_PARTIAL:%.+]] = partial_apply [[PROP1_METHOD]]([[PROP1_OBJ]]) : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject
3334
// CHECK: = apply [[PROP1_PARTIAL]]() : $@callee_owned () -> @owned AnyObject
34-
// CHECK: [[PROP1_FALSE]]:
3535
_ = prop1
3636
}
3737
if let prop2 = obj.innerPointerProp {
3838
// CHECK: dynamic_method_br [[PROP2_OBJ:%.+]] : $@opened([[PROP2_EXISTENTIAL:.+]]) Test, #Test.innerPointerProp!getter.1.foreign, [[PROP2_TRUE:[^,]+]], [[PROP2_FALSE:[^,]+]]
39+
// CHECK: [[PROP2_FALSE]]:
3940
// CHECK: [[PROP2_TRUE]]([[PROP2_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutablePointer<()>):
4041
// CHECK: [[PROP2_PARTIAL:%.+]] = partial_apply [[PROP2_METHOD]]([[PROP2_OBJ]]) : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutablePointer<()>
4142
// CHECK: = apply [[PROP2_PARTIAL]]() : $@callee_owned () -> UnsafeMutablePointer<()>
42-
// CHECK: [[PROP2_FALSE]]:
4343
_ = prop2
4444
}
4545
} // CHECK: {{^}$}}

test/Serialization/Inputs/def_basic.sil

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ bb1:
7777
// CHECK-LABEL: sil public_external [fragile] @test2 : $@convention(thin) (Int) -> ()
7878
sil [fragile] @test2 : $@convention(thin) (Int) -> () {
7979
// CHECK: bb1:
80-
// CHECK: return %5 : $()
80+
// CHECK: %[[VAL:[0-9]+]] = tuple ()
81+
// CHECK: br bb2
8182
// CHECK: bb2:
82-
// CHECK: %5 = tuple ()
83-
// CHECK: br bb1
83+
// CHECK: return %[[VAL]] : $()
8484
bb0(%0 : $Int):
8585
br bb2
8686
bb1:
@@ -602,7 +602,7 @@ bb3(%6 : $Builtin.Word):
602602
sil [fragile] @test_cond_branch_basic_block_args : $@convention(thin) (Int, Builtin.Int1) -> Int {
603603
bb0(%0 : $Int, %1 : $Builtin.Int1):
604604
cond_br %1, bb1(%0 : $Int), bb2(%0 : $Int)
605-
// CHECK: cond_br %1, bb1(%0 : $Int), bb2(%0 : $Int)
605+
// CHECK: cond_br %1, bb2(%0 : $Int), bb1(%0 : $Int)
606606
bb1(%3 : $Int):
607607
br bb3 (%3 : $Int)
608608
bb2(%2 : $Int):
@@ -716,12 +716,13 @@ bb1:
716716
bb2:
717717
%7 = function_ref @_TF6switch1aFT_T_ : $@convention(thin) () -> ()
718718
%8 = apply %7() : $@convention(thin) () -> ()
719-
br bb5 // CHECK: br
719+
br bb5
720720

721721
bb3(%10 : $Int):
722722
// CHECK: unchecked_enum_data {{%.*}} : $MaybePair, #MaybePair.Left!enumelt.1
723723
%x = unchecked_enum_data %3 : $MaybePair, #MaybePair.Left!enumelt.1
724724
br bb4(%x : $Int)
725+
// CHECK: br
725726

726727
bb4(%y : $Int):
727728
%12 = function_ref @_TF6switch1bFT_T_ : $@convention(thin) () -> ()
@@ -763,7 +764,7 @@ bb3:
763764
// CHECK-LABEL: sil public_external [fragile] @test_switch_value : $@convention(thin) (Builtin.Word) -> ()
764765
sil [fragile] @test_switch_value : $@convention(thin) (Builtin.Word) -> () {
765766
bb0(%0 : $Builtin.Word):
766-
// CHECK: switch_value %{{.*}} : $Builtin.Word, case %1: bb1, case %2: bb2
767+
// CHECK: switch_value %{{.*}} : $Builtin.Word, case %1: bb2, case %2: bb1
767768
%1 = integer_literal $Builtin.Word, 1
768769
%2 = integer_literal $Builtin.Word, 2
769770
switch_value %0 : $Builtin.Word, case %1: bb1, case %2: bb2
@@ -1001,7 +1002,7 @@ sil [fragile] @block_invoke : $@convention(c) (@inout_aliasable @block_storage I
10011002
// CHECK-LABEL: sil public_external [fragile] @test_try_apply : $@convention(thin) (@convention(thin) () -> @error Error) -> @error Error {
10021003
sil [fragile] @test_try_apply : $@convention(thin) (@convention(thin) () -> @error Error) -> @error Error {
10031004
bb0(%0 : $@convention(thin) () -> @error Error):
1004-
// CHECK: try_apply %0() : $@convention(thin) () -> @error Error, normal bb1, error bb2
1005+
// CHECK: try_apply %0() : $@convention(thin) () -> @error Error, normal bb2, error bb1
10051006
try_apply %0() : $@convention(thin) () -> @error Error, normal bb1, error bb2
10061007

10071008
bb1(%1 : $()):

test/Serialization/transparent.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ func wrap_br() {
4444
// SIL: bb0(%0 : $MaybePair):
4545
// SIL: retain_value %0 : $MaybePair
4646
// SIL: switch_enum %0 : $MaybePair, case #MaybePair.Neither!enumelt: bb[[CASE1:[0-9]+]], case #MaybePair.Left!enumelt.1: bb[[CASE2:[0-9]+]], case #MaybePair.Right!enumelt.1: bb[[CASE3:[0-9]+]], case #MaybePair.Both!enumelt.1: bb[[CASE4:[0-9]+]]
47-
// SIL: bb[[CASE1]]:
48-
// SIL: bb[[CASE2]](%{{.*}} : $Int32):
49-
// SIL: bb[[CASE3]](%{{.*}} : $String):
5047
// SIL: bb[[CASE4]](%{{.*}} : $(Int32, String)):
48+
// SIL: bb[[CASE3]](%{{.*}} : $String):
49+
// SIL: bb[[CASE2]](%{{.*}} : $Int32):
50+
// SIL: bb[[CASE1]]:
5151
func test_switch(u: MaybePair) {
5252
do_switch(u: u)
5353
}

0 commit comments

Comments
 (0)