mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-12 22:00:41 +02:00
This is incredibly useful and I find myself hacking this feature in every time I am optimizing IR. Adds a new configuration option which allows dumping IR at various times. Before any optimization passes has happened After all optimizations passes have happened Before and After each IRPass to see what is breaking something. Needs #2864 merged first
126 lines
3.9 KiB
C++
126 lines
3.9 KiB
C++
/*
|
|
$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::BEFORE) {
|
|
// Insert at the start.
|
|
it = InsertAt(it, Debug::CreateIRDumper());
|
|
++it; // Skip what we inserted.
|
|
}
|
|
|
|
if ((PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::BEFOREOPT) ||
|
|
(PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::AFTEROPT)) {
|
|
|
|
bool SkipFirstBefore = PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::BEFORE;
|
|
for (; it != Passes.end();) {
|
|
if (PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::BEFOREOPT) {
|
|
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::AFTEROPT) {
|
|
// Insert after
|
|
it = InsertAt(it, Debug::CreateIRDumper());
|
|
++it; // Skip what we inserted.
|
|
}
|
|
}
|
|
}
|
|
if (PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::AFTER) {
|
|
if (!(PassManagerDumpIR() & FEXCore::Config::PassManagerDumpIR::AFTEROPT)) {
|
|
// Insert final IRDumper.
|
|
it = InsertAt(it, Debug::CreateIRDumper());
|
|
}
|
|
}
|
|
}
|
|
|
|
void PassManager::AddDefaultPasses(FEXCore::Context::ContextImpl *ctx, bool InlineConstants, bool StaticRegisterAllocation) {
|
|
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(ctx->HostFeatures.SupportsAVX));
|
|
InsertPass(CreatePassDeadCodeElimination());
|
|
InsertPass(CreateConstProp(InlineConstants, ctx->HostFeatures.SupportsTSOImm9));
|
|
|
|
////// InsertPass(CreateDeadFlagCalculationEliminination());
|
|
|
|
InsertPass(CreateSyscallOptimization());
|
|
InsertPass(CreatePassDeadCodeElimination());
|
|
}
|
|
|
|
// If the IR is compacted post-RA then the node indexing gets messed up and the backend isn't able to find the register assigned to a node
|
|
// Compact before IR, don't worry about RA generating spills/fills
|
|
InsertPass(CreateIRCompaction(ctx->OpDispatcherAllocator), "Compaction");
|
|
}
|
|
|
|
void PassManager::AddDefaultValidationPasses() {
|
|
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
|
|
InsertValidationPass(Validation::CreatePhiValidation());
|
|
InsertValidationPass(Validation::CreateIRValidation(), "IRValidation");
|
|
InsertValidationPass(Validation::CreateRAValidation());
|
|
InsertValidationPass(Validation::CreateValueDominanceValidation());
|
|
#endif
|
|
}
|
|
|
|
void PassManager::InsertRegisterAllocationPass(bool OptimizeSRA, bool SupportsAVX) {
|
|
InsertPass(IR::CreateRegisterAllocationPass(GetPass("Compaction"), OptimizeSRA, SupportsAVX), "RA");
|
|
}
|
|
|
|
bool PassManager::Run(IREmitter *IREmit) {
|
|
FEXCORE_PROFILE_SCOPED("PassManager::Run");
|
|
|
|
bool Changed = false;
|
|
for (auto const &Pass : Passes) {
|
|
Changed |= Pass->Run(IREmit);
|
|
}
|
|
|
|
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
|
|
for (auto const &Pass : ValidationPasses) {
|
|
Changed |= Pass->Run(IREmit);
|
|
}
|
|
#endif
|
|
|
|
return Changed;
|
|
}
|
|
|
|
}
|