58
58
#include " llvm/Support/CommandLine.h"
59
59
#include " llvm/Support/Debug.h"
60
60
61
- // This is temporarily used for testing until Swift 5.5 branches to reduce risk.
62
- llvm::cl::opt<bool > EnableOSSASimplifyCFG (
63
- " enable-ossa-simplify-cfg" ,
64
- llvm::cl::desc (
65
- " Enable non-trivial OSSA simplify-cfg and simple jump threading "
66
- " (staging)." ));
67
-
68
- // This requires new OwnershipOptUtilities which aren't well tested yet.
69
- llvm::cl::opt<bool > EnableOSSARewriteTerminator (
70
- " enable-ossa-rewriteterminator" ,
71
- llvm::cl::desc (
72
- " Enable OSSA simplify-cfg with non-trivial terminator rewriting "
73
- " (staging)." ));
61
+ llvm::cl::opt<bool > EnableOSSACheckedCastBrJumpThreading (
62
+ " enable-ossa-checked-cast-br-jump-threading" ,
63
+ llvm::cl::desc (" Enable OSSA checked cast branch jump threading "
64
+ " (staging)." ),
65
+ llvm::cl::init(true ));
66
+
67
+ llvm::cl::opt<bool > EnableOSSASimpleJumpThreading (
68
+ " enable-ossa-simple-jump-threading" ,
69
+ llvm::cl::desc (" Enable OSSA simple jump threading (staging)." ),
70
+ llvm::cl::init(true ));
71
+
72
+ llvm::cl::opt<bool > EnableOSSADominatorBasedSimplify (
73
+ " enable-ossa-dominator-based-simplify" ,
74
+ llvm::cl::desc (" Enable OSSA dominator based simplifications (staging)." ),
75
+ llvm::cl::init(true ));
74
76
75
77
llvm::cl::opt<bool > IsInfiniteJumpThreadingBudget (
76
78
" sil-infinite-jump-threading-budget" ,
@@ -183,7 +185,6 @@ bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
183
185
return false ;
184
186
185
187
Cloner.cloneBranchTarget (SrcTerm);
186
-
187
188
// We have copied the threaded block into the edge.
188
189
auto *clonedSrc = Cloner.getNewBB ();
189
190
SmallVector<SILBasicBlock *, 4 > clonedSuccessors (
@@ -207,7 +208,6 @@ bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
207
208
ThreadedSuccessorBlock, Args);
208
209
209
210
CondTerm->eraseFromParent ();
210
-
211
211
} else {
212
212
// Get the enum element and the destination block of the block we jump
213
213
// thread.
@@ -217,21 +217,29 @@ bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
217
217
// Instantiate the payload if necessary.
218
218
SILBuilderWithScope Builder (SEI);
219
219
if (!ThreadedSuccessorBlock->args_empty ()) {
220
- auto EnumVal = SEI->getOperand ();
221
- auto EnumTy = EnumVal->getType ();
222
- auto Loc = SEI->getLoc ();
223
- auto Ty = EnumTy.getEnumElementType (ti.EnumCase , SEI->getModule (),
224
- Builder.getTypeExpansionContext ());
225
- SILValue UED (
226
- Builder.createUncheckedEnumData (Loc, EnumVal, ti.EnumCase , Ty));
227
- assert (UED->getType ()
228
- == (*ThreadedSuccessorBlock->args_begin ())->getType ()
229
- && " Argument types must match" );
230
- Builder.createBranch (SEI->getLoc (), ThreadedSuccessorBlock, {UED});
231
-
220
+ if (ti.EnumCase ->hasAssociatedValues () &&
221
+ (!SEI->hasDefault () ||
222
+ ThreadedSuccessorBlock != SEI->getDefaultBB ())) {
223
+ auto EnumVal = SEI->getOperand ();
224
+ auto EnumTy = EnumVal->getType ();
225
+ auto Loc = SEI->getLoc ();
226
+ auto Ty = EnumTy.getEnumElementType (ti.EnumCase , SEI->getModule (),
227
+ Builder.getTypeExpansionContext ());
228
+ SILValue UED (
229
+ Builder.createUncheckedEnumData (Loc, EnumVal, ti.EnumCase , Ty));
230
+ assert (UED->getType () ==
231
+ (*ThreadedSuccessorBlock->args_begin ())->getType () &&
232
+ " Argument types must match" );
233
+ Builder.createBranch (SEI->getLoc (), ThreadedSuccessorBlock, {UED});
234
+ } else {
235
+ assert (SEI->getDefaultBB () == ThreadedSuccessorBlock);
236
+ auto *OldBlockArg = ThreadedSuccessorBlock->getArgument (0 );
237
+ OldBlockArg->replaceAllUsesWith (SEI->getOperand ());
238
+ ThreadedSuccessorBlock->eraseArgument (0 );
239
+ Builder.createBranch (SEI->getLoc (), ThreadedSuccessorBlock);
240
+ }
232
241
} else {
233
- Builder.createBranch (SEI->getLoc (), ThreadedSuccessorBlock,
234
- ArrayRef<SILValue>());
242
+ Builder.createBranch (SEI->getLoc (), ThreadedSuccessorBlock);
235
243
}
236
244
SEI->eraseFromParent ();
237
245
}
@@ -495,11 +503,15 @@ bool SimplifyCFG::simplifyThreadedTerminators() {
495
503
if (auto *EI = dyn_cast<EnumInst>(SEI->getOperand ())) {
496
504
LLVM_DEBUG (llvm::dbgs () << " simplify threaded " << *SEI);
497
505
auto *LiveBlock = SEI->getCaseDestination (EI->getElement ());
498
- if (EI->hasOperand () && !LiveBlock->args_empty ())
499
- SILBuilderWithScope (SEI)
500
- .createBranch (SEI->getLoc (), LiveBlock, EI->getOperand ());
501
- else
506
+ if (!LiveBlock->args_empty ()) {
507
+ auto *LiveBlockArg = LiveBlock->getArgument (0 );
508
+ auto NewValue = EI->hasOperand () ? EI->getOperand () : EI;
509
+ LiveBlockArg->replaceAllUsesWith (NewValue);
510
+ LiveBlock->eraseArgument (0 );
511
+ SILBuilderWithScope (SEI).createBranch (SEI->getLoc (), LiveBlock);
512
+ } else {
502
513
SILBuilderWithScope (SEI).createBranch (SEI->getLoc (), LiveBlock);
514
+ }
503
515
SEI->eraseFromParent ();
504
516
if (EI->use_empty ())
505
517
EI->eraseFromParent ();
@@ -536,7 +548,7 @@ bool SimplifyCFG::dominatorBasedSimplify(DominanceAnalysis *DA) {
536
548
// Get the dominator tree.
537
549
DT = DA->get (&Fn);
538
550
539
- if (!EnableOSSASimplifyCFG && Fn.hasOwnership ())
551
+ if (!EnableOSSADominatorBasedSimplify && Fn.hasOwnership ())
540
552
return false ;
541
553
542
554
// Split all critical edges such that we can move code onto edges. This is
@@ -560,7 +572,7 @@ bool SimplifyCFG::dominatorBasedSimplify(DominanceAnalysis *DA) {
560
572
// and MUST NOT change the CFG without updating the dominator tree to
561
573
// reflect such change.
562
574
if (tryCheckedCastBrJumpThreading (&Fn, DT, deBlocks, BlocksForWorklist,
563
- EnableOSSARewriteTerminator )) {
575
+ EnableOSSACheckedCastBrJumpThreading )) {
564
576
for (auto BB: BlocksForWorklist)
565
577
addToWorklist (BB);
566
578
@@ -907,19 +919,13 @@ static bool hasInjectedEnumAtEndOfBlock(SILBasicBlock *block, SILValue enumAddr)
907
919
// / tryJumpThreading - Check to see if it looks profitable to duplicate the
908
920
// / destination of an unconditional jump into the bottom of this block.
909
921
bool SimplifyCFG::tryJumpThreading (BranchInst *BI) {
910
- if (!EnableOSSASimplifyCFG && Fn.hasOwnership ())
922
+ if (!EnableOSSASimpleJumpThreading && Fn.hasOwnership ())
911
923
return false ;
912
924
913
925
auto *DestBB = BI->getDestBB ();
914
926
auto *SrcBB = BI->getParent ();
915
927
TermInst *destTerminator = DestBB->getTerminator ();
916
- if (!EnableOSSARewriteTerminator && Fn.hasOwnership ()) {
917
- if (llvm::any_of (DestBB->getArguments (), [this ](SILValue op) {
918
- return !op->getType ().isTrivial (Fn);
919
- })) {
920
- return false ;
921
- }
922
- }
928
+
923
929
// If the destination block ends with a return, we don't want to duplicate it.
924
930
// We want to maintain the canonical form of a single return where possible.
925
931
if (destTerminator->isFunctionExiting ())
@@ -948,14 +954,13 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
948
954
for (unsigned i : indices (BI->getArgs ())) {
949
955
SILValue Arg = BI->getArg (i);
950
956
951
- // TODO: Verify if we need to jump thread to remove releases in OSSA.
952
957
// If the value being substituted on is release there is a chance we could
953
958
// remove the release after jump threading.
954
- if (!Arg-> getType (). isTrivial (*SrcBB-> getParent ()) &&
955
- couldRemoveRelease ( SrcBB, Arg, DestBB,
956
- DestBB->getArgument (i))) {
957
- ThreadingBudget = 8 ;
958
- break ;
959
+ // In ossa, copy propagation can do this, avoid jump threading.
960
+ if (!Fn. hasOwnership () && !Arg-> getType (). isTrivial (* SrcBB-> getParent ()) &&
961
+ couldRemoveRelease (SrcBB, Arg, DestBB, DestBB->getArgument (i))) {
962
+ ThreadingBudget = 8 ;
963
+ break ;
959
964
}
960
965
961
966
// If the value being substituted is an enum, check to see if there are any
@@ -2954,10 +2959,8 @@ static bool shouldTailDuplicate(SILBasicBlock &Block) {
2954
2959
bool SimplifyCFG::tailDuplicateObjCMethodCallSuccessorBlocks () {
2955
2960
SmallVector<SILBasicBlock *, 16 > ObjCBlocks;
2956
2961
2957
- // TODO: OSSA phi support. Even if all block arguments are trivial,
2958
- // jump-threading may require creation of guaranteed phis, which may require
2959
- // creation of nested borrow scopes.
2960
- if (!EnableOSSARewriteTerminator && Fn.hasOwnership ()) {
2962
+ if (Fn.hasOwnership ()) {
2963
+ // TODO: This needs additional support in ossa.
2961
2964
return false ;
2962
2965
}
2963
2966
// Collect blocks to tail duplicate.
@@ -3166,8 +3169,8 @@ RemoveDeadArgsWhenSplitting("sroa-args-remove-dead-args-after",
3166
3169
llvm::cl::init (true ));
3167
3170
3168
3171
bool ArgumentSplitter::split () {
3169
- if (!EnableOSSARewriteTerminator && Arg->getFunction ()->hasOwnership ()) {
3170
- // TODO: OSSA phi support
3172
+ if (Arg->getFunction ()->hasOwnership ()) {
3173
+ // TODO: Additional work is needed to create non-trivial projections in ossa
3171
3174
if (!Arg->getType ().isTrivial (*Arg->getFunction ()))
3172
3175
return false ;
3173
3176
}
@@ -3688,6 +3691,19 @@ bool SimplifyCFG::simplifyArgument(SILBasicBlock *BB, unsigned i) {
3688
3691
auto *Use = *A->use_begin ();
3689
3692
auto *User = Use->getUser ();
3690
3693
3694
+ auto disableInOSSA = [](SingleValueInstruction *inst) {
3695
+ assert (isa<StructInst>(inst) || isa<TupleInst>(inst) ||
3696
+ isa<EnumInst>(inst));
3697
+ if (!inst->getFunction ()->hasOwnership ()) {
3698
+ return false ;
3699
+ }
3700
+ if (inst->getOwnershipKind () == OwnershipKind::Owned)
3701
+ return !inst->getSingleUse ();
3702
+ if (BorrowedValue borrow = BorrowedValue (inst->getOperand (0 )))
3703
+ return borrow.isLocalScope ();
3704
+ return false ;
3705
+ };
3706
+
3691
3707
// Handle projections.
3692
3708
if (!isa<StructExtractInst>(User) &&
3693
3709
!isa<TupleExtractInst>(User) &&
@@ -3702,15 +3718,17 @@ bool SimplifyCFG::simplifyArgument(SILBasicBlock *BB, unsigned i) {
3702
3718
return false ;
3703
3719
auto *Branch = cast<BranchInst>(Pred->getTerminator ());
3704
3720
SILValue BranchArg = Branch->getArg (i);
3705
- if (isa<StructInst>(BranchArg))
3706
- continue ;
3707
- if (isa<TupleInst>(BranchArg))
3708
- continue ;
3721
+ if (! isa<StructInst>(BranchArg) && !isa<TupleInst>(BranchArg) &&
3722
+ !isa<EnumInst>(BranchArg)) {
3723
+ return false ;
3724
+ }
3709
3725
if (auto *EI = dyn_cast<EnumInst>(BranchArg)) {
3710
- if (EI->getElement () == cast<UncheckedEnumDataInst>(proj)->getElement ())
3711
- continue ;
3726
+ if (EI->getElement () != cast<UncheckedEnumDataInst>(proj)->getElement ())
3727
+ return false ;
3728
+ }
3729
+ if (disableInOSSA (cast<SingleValueInstruction>(BranchArg))) {
3730
+ return false ;
3712
3731
}
3713
- return false ;
3714
3732
}
3715
3733
3716
3734
// Okay, we'll replace the BB arg with one with the right type, replace
0 commit comments