mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[SILOptimizer] Turn "is self-recursive" check into analysis
The body of a function has to be re-analyzed for every call site of the function, which is very expensive and if the body is not changed would produce the same result. This takes about ~10% from swift-syntax overall build time in release configuration.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "swift/SIL/PatternMatch.h"
|
||||
#include "swift/SIL/SILCloner.h"
|
||||
#include "swift/SILOptimizer/Analysis/LoopAnalysis.h"
|
||||
#include "swift/SILOptimizer/Analysis/IsSelfRecursiveAnalysis.h"
|
||||
#include "swift/SILOptimizer/PassManager/Passes.h"
|
||||
#include "swift/SILOptimizer/PassManager/Transforms.h"
|
||||
#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
|
||||
@@ -209,7 +210,8 @@ static std::optional<uint64_t> getMaxLoopTripCount(SILLoop *Loop,
|
||||
/// Check whether we can duplicate the instructions in the loop and use a
|
||||
/// heuristic that looks at the trip count and the cost of the instructions in
|
||||
/// the loop to determine whether we should unroll this loop.
|
||||
static bool canAndShouldUnrollLoop(SILLoop *Loop, uint64_t TripCount) {
|
||||
static bool canAndShouldUnrollLoop(SILLoop *Loop, uint64_t TripCount,
|
||||
IsSelfRecursiveAnalysis *SRA) {
|
||||
assert(Loop->getSubLoops().empty() && "Expect innermost loops");
|
||||
if (TripCount > 32)
|
||||
return false;
|
||||
@@ -231,7 +233,7 @@ static bool canAndShouldUnrollLoop(SILLoop *Loop, uint64_t TripCount) {
|
||||
++Cost;
|
||||
if (auto AI = FullApplySite::isa(&Inst)) {
|
||||
auto Callee = AI.getCalleeFunction();
|
||||
if (Callee && getEligibleFunction(AI, InlineSelection::Everything)) {
|
||||
if (Callee && getEligibleFunction(AI, InlineSelection::Everything, SRA)) {
|
||||
// If callee is rather big and potentially inlinable, it may be better
|
||||
// not to unroll, so that the body of the callee can be inlined later.
|
||||
Cost += Callee->size() * InsnsPerBB;
|
||||
@@ -386,7 +388,7 @@ updateSSA(SILFunction *Fn, SILLoop *Loop,
|
||||
|
||||
/// Try to fully unroll the loop if we can determine the trip count and the trip
|
||||
/// count is below a threshold.
|
||||
static bool tryToUnrollLoop(SILLoop *Loop) {
|
||||
static bool tryToUnrollLoop(SILLoop *Loop, IsSelfRecursiveAnalysis *SRA) {
|
||||
assert(Loop->getSubLoops().empty() && "Expecting innermost loops");
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "Trying to unroll loop : \n" << *Loop);
|
||||
@@ -407,7 +409,7 @@ static bool tryToUnrollLoop(SILLoop *Loop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!canAndShouldUnrollLoop(Loop, MaxTripCount.value())) {
|
||||
if (!canAndShouldUnrollLoop(Loop, MaxTripCount.value(), SRA)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Not unrolling, exceeds cost threshold\n");
|
||||
return false;
|
||||
}
|
||||
@@ -487,6 +489,7 @@ class LoopUnrolling : public SILFunctionTransform {
|
||||
bool Changed = false;
|
||||
auto *Fun = getFunction();
|
||||
SILLoopInfo *LoopInfo = PM->getAnalysis<SILLoopAnalysis>()->get(Fun);
|
||||
IsSelfRecursiveAnalysis *SRA = PM->getAnalysis<IsSelfRecursiveAnalysis>();
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "Loop Unroll running on function : "
|
||||
<< Fun->getName() << "\n");
|
||||
@@ -514,7 +517,7 @@ class LoopUnrolling : public SILFunctionTransform {
|
||||
|
||||
// Try to unroll innermost loops.
|
||||
for (auto *Loop : InnermostLoops)
|
||||
Changed |= tryToUnrollLoop(Loop);
|
||||
Changed |= tryToUnrollLoop(Loop, SRA);
|
||||
|
||||
if (Changed) {
|
||||
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
|
||||
|
||||
Reference in New Issue
Block a user