[FuncSpec] Don't run the solver if there's nothing to do

Even if there are no interesting functions, the SCCP solver would still run
before bailing. Now bail earlier, avoid running the solver for nothing.

Differential Revision: https://reviews.llvm.org/D111645
This commit is contained in:
Sjoerd Meijer 2021-10-12 15:37:21 +01:00
parent 621d7a75b1
commit 67a58fa3a6
2 changed files with 66 additions and 3 deletions

View File

@ -789,12 +789,27 @@ bool llvm::runFunctionSpecialization(
Solver.trackValueOfGlobalVariable(&G); Solver.trackValueOfGlobalVariable(&G);
} }
auto &TrackedFuncs = Solver.getArgumentTrackedFunctions();
SmallVector<Function *, 16> FuncDecls(TrackedFuncs.begin(),
TrackedFuncs.end());
// No tracked functions, so nothing to do: don't run the solver and remove
// the ssa_copy intrinsics that may have been introduced.
if (TrackedFuncs.empty()) {
removeSSACopy(M);
return false;
}
// Solve for constants. // Solve for constants.
auto RunSCCPSolver = [&](auto &WorkList) { auto RunSCCPSolver = [&](auto &WorkList) {
bool ResolvedUndefs = true; bool ResolvedUndefs = true;
while (ResolvedUndefs) { while (ResolvedUndefs) {
// Not running the solver unnecessary is checked in regression test
// nothing-to-do.ll, so if this debug message is changed, this regression
// test needs updating too.
LLVM_DEBUG(dbgs() << "FnSpecialization: Running solver\n"); LLVM_DEBUG(dbgs() << "FnSpecialization: Running solver\n");
Solver.solve(); Solver.solve();
LLVM_DEBUG(dbgs() << "FnSpecialization: Resolving undefs\n"); LLVM_DEBUG(dbgs() << "FnSpecialization: Resolving undefs\n");
ResolvedUndefs = false; ResolvedUndefs = false;
@ -815,9 +830,6 @@ bool llvm::runFunctionSpecialization(
} }
}; };
auto &TrackedFuncs = Solver.getArgumentTrackedFunctions();
SmallVector<Function *, 16> FuncDecls(TrackedFuncs.begin(),
TrackedFuncs.end());
#ifndef NDEBUG #ifndef NDEBUG
LLVM_DEBUG(dbgs() << "FnSpecialization: Worklist fn decls:\n"); LLVM_DEBUG(dbgs() << "FnSpecialization: Worklist fn decls:\n");
for (auto *F : FuncDecls) for (auto *F : FuncDecls)

View File

@ -0,0 +1,51 @@
; REQUIRES: asserts
; RUN: opt -function-specialization -debug -S < %s 2>&1 | FileCheck %s
; The purpose of this test is to check that we don't run the solver as there's
; nothing to do here. For a test that doesn't trigger function specialisation,
; it is intentionally 'big' because we also want to check that the ssa.copy
; intrinsics that are introduced by the solver are cleaned up if we bail
; early. Thus, first check the debug messages for the introduction of these
; intrinsics:
; CHECK: FnSpecialization: Analysing decl: foo
; CHECK: Found replacement{{.*}} call i32 @llvm.ssa.copy.i32
; CHECK: Found replacement{{.*}} call i32 @llvm.ssa.copy.i32
; Then, make sure the solver didn't run:
; CHECK-NOT: Running solver
; Finally, check the absence and thus removal of these intrinsics:
; CHECK-LABEL: @foo
; CHECK-NOT: call i32 @llvm.ssa.copy.i32
@N = external dso_local global i32, align 4
@B = external dso_local global i32*, align 8
@A = external dso_local global i32*, align 8
define dso_local i32 @foo() {
entry:
br label %for.cond
for.cond:
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%0 = load i32, i32* @N, align 4
%cmp = icmp slt i32 %i.0, %0
br i1 %cmp, label %for.body, label %for.cond.cleanup
for.cond.cleanup:
ret i32 undef
for.body:
%1 = load i32*, i32** @B, align 8
%idxprom = sext i32 %i.0 to i64
%arrayidx = getelementptr inbounds i32, i32* %1, i64 %idxprom
%2 = load i32, i32* %arrayidx, align 4
%3 = load i32*, i32** @A, align 8
%arrayidx2 = getelementptr inbounds i32, i32* %3, i64 %idxprom
store i32 %2, i32* %arrayidx2, align 4
%inc = add nsw i32 %i.0, 1
br label %for.cond
}