diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp index bcaac377c32..54a5ae65c88 100644 --- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp +++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp @@ -802,10 +802,12 @@ static int getThreadingCost(SILInstruction *I) { return 0; } +static int maxBranchRecursionDepth = 6; /// couldSimplifyUsers - Check to see if any simplifications are possible if /// "Val" is substituted for BBArg. If so, return true, if nothing obvious /// is possible, return false. -static bool couldSimplifyEnumUsers(SILArgument *BBArg, int Budget) { +static bool couldSimplifyEnumUsers(SILArgument *BBArg, int Budget, + int recursionDepth = 0) { SILBasicBlock *BB = BBArg->getParent(); int BudgetForBranch = 100; @@ -833,6 +835,9 @@ static bool couldSimplifyEnumUsers(SILArgument *BBArg, int Budget) { } if (auto *BI = dyn_cast(User)) { + if (recursionDepth >= maxBranchRecursionDepth) { + return false; + } if (BudgetForBranch > Budget) { BudgetForBranch = Budget; for (SILInstruction &I : *BB) { @@ -844,7 +849,8 @@ static bool couldSimplifyEnumUsers(SILArgument *BBArg, int Budget) { if (BudgetForBranch > 0) { SILBasicBlock *DestBB = BI->getDestBB(); unsigned OpIdx = UI->getOperandNumber(); - if (couldSimplifyEnumUsers(DestBB->getArgument(OpIdx), BudgetForBranch)) + if (couldSimplifyEnumUsers(DestBB->getArgument(OpIdx), BudgetForBranch, + recursionDepth + 1)) return true; } } diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp index 6d928f5633f..d5fe59ce1ad 100644 --- a/lib/SILOptimizer/Utils/SILInliner.cpp +++ b/lib/SILOptimizer/Utils/SILInliner.cpp @@ -790,6 +790,11 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) { case SILInstructionKind::GetAsyncContinuationInst: return InlineCost::Free; + // Unconditional branch is free in empty blocks. + case SILInstructionKind::BranchInst: + return (I.getIterator() == I.getParent()->begin()) + ? InlineCost::Free : InlineCost::Expensive; + case SILInstructionKind::AbortApplyInst: case SILInstructionKind::ApplyInst: case SILInstructionKind::TryApplyInst: @@ -804,7 +809,6 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) { case SILInstructionKind::WitnessMethodInst: case SILInstructionKind::AssignInst: case SILInstructionKind::AssignByWrapperInst: - case SILInstructionKind::BranchInst: case SILInstructionKind::CheckedCastBranchInst: case SILInstructionKind::CheckedCastValueBranchInst: case SILInstructionKind::CheckedCastAddrBranchInst: diff --git a/test/SILOptimizer/inliner_spa.sil b/test/SILOptimizer/inliner_spa.sil index ba18bcb98b5..01beb057dd1 100644 --- a/test/SILOptimizer/inliner_spa.sil +++ b/test/SILOptimizer/inliner_spa.sil @@ -19,10 +19,10 @@ bb0: } // CHECK-LABEL: SPA @test_if_then_else -// CHECK-NEXT: bb0: length=1+0, d-entry=0, d-exit=2 +// CHECK-NEXT: bb0: length=1+0, d-entry=0, d-exit=1 // CHECK-NEXT: bb1: length=3+0, d-entry=1, d-exit=3 -// CHECK-NEXT: bb2: length=1+0, d-entry=1, d-exit=1 -// CHECK-NEXT: bb3: length=0+0, d-entry=2, d-exit=0 +// CHECK-NEXT: bb2: length=0+0, d-entry=1, d-exit=0 +// CHECK-NEXT: bb3: length=0+0, d-entry=1, d-exit=0 sil @test_if_then_else : $@convention(thin) () -> () { bb0: @@ -42,9 +42,9 @@ bb3: } // CHECK-LABEL: SPA @test_simple_loop -// CHECK-NEXT: bb0: length=1+0, d-entry=0, d-exit=34 -// CHECK-NEXT: bb1: length=3+30, d-entry=1, d-exit=33 -// CHECK-NEXT: bb2: length=0+0, d-entry=34, d-exit=0 +// CHECK-NEXT: bb0: length=0+0, d-entry=0, d-exit=33 +// CHECK-NEXT: bb1: length=3+30, d-entry=0, d-exit=33 +// CHECK-NEXT: bb2: length=0+0, d-entry=33, d-exit=0 // CHECK-NEXT: Loop bb1: // CHECK-NEXT: bb1: length=3+0, d-entry=0, d-exit=3 @@ -64,9 +64,9 @@ bb2: // CHECK-LABEL: SPA @test_loop_with_bypass_edge // CHECK-NEXT: bb0: length=1+30, d-entry=0, d-exit=31 -// CHECK-NEXT: bb1: length=1+0, d-entry=31, d-exit=5 -// CHECK-NEXT: bb2: length=3+0, d-entry=32, d-exit=4 -// CHECK-NEXT: bb3: length=1+0, d-entry=35, d-exit=1 +// CHECK-NEXT: bb1: length=0+0, d-entry=31, d-exit=3 +// CHECK-NEXT: bb2: length=3+0, d-entry=31, d-exit=3 +// CHECK-NEXT: bb3: length=0+0, d-entry=34, d-exit=0 // CHECK-NEXT: bb4: length=0+0, d-entry=31, d-exit=0 // CHECK-NEXT: Loop bb2: // CHECK-NEXT: bb2: length=3+0, d-entry=0, d-exit=3 @@ -93,12 +93,12 @@ bb4: // CHECK-LABEL: SPA @test_nested_loops // CHECK-NEXT: bb0: length=1+40, d-entry=0, d-exit=41 -// CHECK-NEXT: bb1: length=1+0, d-entry=41, d-exit=6 -// CHECK-NEXT: bb2: length=1+0, d-entry=42, d-exit=5 -// CHECK-NEXT: bb3: length=3+0, d-entry=43, d-exit=5 -// CHECK-NEXT: bb4: length=2+0, d-entry=43, d-exit=4 -// CHECK-NEXT: bb5: length=1+0, d-entry=45, d-exit=2 -// CHECK-NEXT: bb6: length=1+0, d-entry=46, d-exit=1 +// CHECK-NEXT: bb1: length=0+0, d-entry=41, d-exit=4 +// CHECK-NEXT: bb2: length=1+0, d-entry=41, d-exit=4 +// CHECK-NEXT: bb3: length=3+0, d-entry=42, d-exit=4 +// CHECK-NEXT: bb4: length=2+0, d-entry=42, d-exit=3 +// CHECK-NEXT: bb5: length=1+0, d-entry=44, d-exit=1 +// CHECK-NEXT: bb6: length=0+0, d-entry=45, d-exit=0 // CHECK-NEXT: bb7: length=0+0, d-entry=41, d-exit=0 // CHECK-NEXT: Loop bb2: // CHECK-NEXT: bb2: length=1+0, d-entry=0, d-exit=4 @@ -146,9 +146,9 @@ bb0: } // CHECK-LABEL: SPA @test_call_of_noreturn_in_loop -// CHECK-NEXT: bb0: length=1+0, d-entry=0, d-exit=133 -// CHECK-NEXT: bb1: length=12+120, d-entry=1, d-exit=132 -// CHECK-NEXT: bb2: length=0+0, d-entry=133, d-exit=0 +// CHECK-NEXT: bb0: length=0+0, d-entry=0, d-exit=132 +// CHECK-NEXT: bb1: length=12+120, d-entry=0, d-exit=132 +// CHECK-NEXT: bb2: length=0+0, d-entry=132, d-exit=0 // CHECK-NEXT: Loop bb1: // CHECK-NEXT: bb1: length=12+0, d-entry=0, d-exit=12 sil @test_call_of_noreturn_in_loop : $@convention(thin) () -> () {