18
18
#define SWIFT_SIL_SILCLONER_H
19
19
20
20
#include " swift/AST/ProtocolConformance.h"
21
- #include " swift/SIL/SILOpenedArchetypesTracker.h"
21
+ #include " swift/SIL/BasicBlockUtils.h"
22
+ #include " swift/SIL/Dominance.h"
22
23
#include " swift/SIL/SILBuilder.h"
23
24
#include " swift/SIL/SILDebugScope.h"
25
+ #include " swift/SIL/SILOpenedArchetypesTracker.h"
24
26
#include " swift/SIL/SILVisitor.h"
25
27
26
28
namespace swift {
@@ -44,6 +46,7 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
44
46
// / MARK: Context shared with CRTP extensions.
45
47
46
48
SILBuilder Builder;
49
+ DominanceInfo *DomTree = nullptr ;
47
50
TypeSubstitutionMap OpenedExistentialSubs;
48
51
SILOpenedArchetypesTracker OpenedArchetypesTracker;
49
52
@@ -75,12 +78,15 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
75
78
using SILInstructionVisitor<ImplClass>::asImpl;
76
79
77
80
explicit SILCloner (SILFunction &F,
78
- SILOpenedArchetypesTracker &OpenedArchetypesTracker)
79
- : Builder(F), OpenedArchetypesTracker(OpenedArchetypesTracker) {
81
+ SILOpenedArchetypesTracker &OpenedArchetypesTracker,
82
+ DominanceInfo *DT = nullptr )
83
+ : Builder(F), DomTree(DT),
84
+ OpenedArchetypesTracker(OpenedArchetypesTracker) {
80
85
Builder.setOpenedArchetypesTracker (&OpenedArchetypesTracker);
81
86
}
82
87
83
- explicit SILCloner (SILFunction &F) : Builder(F), OpenedArchetypesTracker(&F) {
88
+ explicit SILCloner (SILFunction &F, DominanceInfo *DT = nullptr )
89
+ : Builder(F), DomTree(DT), OpenedArchetypesTracker(&F) {
84
90
Builder.setOpenedArchetypesTracker (&OpenedArchetypesTracker);
85
91
}
86
92
@@ -442,8 +448,9 @@ class SILClonerWithScopes : public SILCloner<ImplClass> {
442
448
public:
443
449
SILClonerWithScopes (SILFunction &To,
444
450
SILOpenedArchetypesTracker &OpenedArchetypesTracker,
451
+ DominanceInfo *DT = nullptr ,
445
452
bool Disable = false )
446
- : SILCloner<ImplClass>(To, OpenedArchetypesTracker) {
453
+ : SILCloner<ImplClass>(To, OpenedArchetypesTracker, DT ) {
447
454
448
455
// We only want to do this when we generate cloned functions, not
449
456
// when we inline.
@@ -694,17 +701,36 @@ void SILCloner<ImplClass>::visitBlocksDepthFirst(SILBasicBlock *startBB) {
694
701
asImpl ().visitInstructionsInBlock (BB);
695
702
696
703
unsigned dfsSuccStartIdx = dfsWorklist.size ();
697
- for (auto &succ : BB->getSuccessors ()) {
704
+
705
+ // splitEdge may rewrite BB's successors during this loop.
706
+ for (unsigned succIdx = 0 , numSucc = BB->getSuccessors ().size ();
707
+ succIdx != numSucc; ++succIdx) {
708
+
698
709
// Only visit a successor that has not already been visited and was not
699
710
// premapped by the client.
700
- if (BBMap.count (succ))
701
- continue ;
702
-
711
+ if (BBMap.count (BB->getSuccessors ()[succIdx])) {
712
+ // After cloning BB, this successor may be a new CFG merge. If it is
713
+ // valid to branch directly from the BB to its clone do nothing; if not,
714
+ // split the edge from BB->succ and clone the new block.
715
+ //
716
+ // A CFG merge may require new block arguments, so check for both a
717
+ // critical edge and the ability to add branch arguments (BranchInst).
718
+ if (BB->getSingleSuccessorBlock ()
719
+ && isa<BranchInst>(BB->getTerminator ())) {
720
+ continue ;
721
+ }
722
+ // This predecessor has multiple successors, so cloning it without
723
+ // cloning its successors would create a critical edge.
724
+ splitEdge (BB->getTerminator (), succIdx, DomTree);
725
+ assert (!BBMap.count (BB->getSuccessors ()[succIdx]));
726
+ }
703
727
// Map the successor to a new BB. Layout the cloned blocks in the order
704
728
// they are visited and cloned.
705
729
lastClonedBB =
706
730
getBuilder ().getFunction ().createBasicBlockAfter (lastClonedBB);
707
731
732
+ // After splitting, BB has stable successors.
733
+ auto &succ = BB->getSuccessors ()[succIdx];
708
734
BBMap.insert (std::make_pair (succ.getBB (), lastClonedBB));
709
735
710
736
dfsWorklist.push_back (succ);
0 commit comments