Files
FEX-Emu--FEX/FEXCore/Source/Interface/IR/PassManager.cpp
T
Alyssa Rosenzweig 676c9a9be6 IR: do not return progress from passes
Generally, there are three reasons to track progress:

* Conditional optimizations. E.g. only run DCE if ConstProp succeeds.
* Fixed point optimizations. E.g. keep running the opt loop until convergence.
* Metadata shenianigans.

None of these apply to FEX. We explicitly do not want a nonlinear pass ordering,
instead we want just a few passes that each converge in a single iteration. We
expect them all to make progress when run. As such, tracking progress is a waste
of CPU cycles. Stop doing it.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2024-05-24 15:44:49 -04:00

117 lines
3.4 KiB
C++

// SPDX-License-Identifier: MIT
/*
$info$
meta: ir|opts ~ IR to IR Optimization
tags: ir|opts
desc: Defines which passes are run, and runs them
$end_info$
*/
#include "Interface/Context/Context.h"
#include "Interface/IR/PassManager.h"
#include "Interface/IR/Passes.h"
#include "Interface/IR/Passes/RegisterAllocationPass.h"
#include <FEXCore/Config/Config.h>
#include <FEXCore/Utils/Profiler.h>
namespace FEXCore::IR {
class IREmitter;
void PassManager::Finalize() {
if (!PassManagerDumpIR()) {
// Not configured to dump any IR, just return.
return;
}
auto it = Passes.begin();
// Walk the passes and add them where asked.
if (PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::BEFOREOPT) {
// Insert at the start.
it = InsertAt(it, Debug::CreateIRDumper());
++it; // Skip what we inserted.
}
if ((PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::BEFOREPASS) ||
(PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::AFTERPASS)) {
bool SkipFirstBefore = PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::BEFOREOPT;
for (; it != Passes.end();) {
if (PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::BEFOREPASS) {
if (SkipFirstBefore) {
// If we need to skip the first one, then continue.
SkipFirstBefore = false;
++it;
continue;
}
// Insert before
it = InsertAt(it, Debug::CreateIRDumper());
++it; // Skip what we inserted.
}
++it; // Skip current pass.
if (PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::AFTERPASS) {
// Insert after
it = InsertAt(it, Debug::CreateIRDumper());
++it; // Skip what we inserted.
}
}
}
if (PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::AFTEROPT) {
if (!(PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::AFTERPASS)) {
// Insert final IRDumper.
InsertAt(Passes.end(), Debug::CreateIRDumper());
}
}
}
void PassManager::AddDefaultPasses(FEXCore::Context::ContextImpl* ctx, bool InlineConstants) {
FEX_CONFIG_OPT(DisablePasses, O0);
if (!DisablePasses()) {
InsertPass(CreateContextLoadStoreElimination(ctx->HostFeatures.SupportsAVX));
if (Is64BitMode()) {
// This needs to run after RCLSE
// This only matters for 64-bit code since these instructions don't exist in 32-bit
InsertPass(CreateLongDivideEliminationPass());
}
InsertPass(CreateDeadStoreElimination());
InsertPass(CreatePassDeadCodeElimination());
InsertPass(CreateConstProp(InlineConstants, ctx->HostFeatures.SupportsTSOImm9, Is64BitMode()));
InsertPass(CreateDeadFlagCalculationEliminination());
InsertPass(CreateInlineCallOptimization(&ctx->CPUID));
InsertPass(CreatePassDeadCodeElimination());
}
}
void PassManager::AddDefaultValidationPasses() {
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
InsertValidationPass(Validation::CreateIRValidation(), "IRValidation");
InsertValidationPass(Validation::CreateRAValidation());
#endif
}
void PassManager::InsertRegisterAllocationPass() {
InsertPass(IR::CreateRegisterAllocationPass(), "RA");
}
void PassManager::Run(IREmitter* IREmit) {
FEXCORE_PROFILE_SCOPED("PassManager::Run");
for (const auto& Pass : Passes) {
Pass->Run(IREmit);
}
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
for (const auto& Pass : ValidationPasses) {
Pass->Run(IREmit);
}
#endif
}
} // namespace FEXCore::IR