mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
SPU LLVM: upgrade custom DSE pass
This commit is contained in:
parent
6981cbb985
commit
183bea3b98
@ -3921,6 +3921,8 @@ void spu_recompiler_base::dump(const spu_program& result, std::string& out)
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Analysis/PostDominators.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
@ -5453,11 +5455,19 @@ public:
|
||||
}
|
||||
|
||||
// Work on register stores.
|
||||
// 1. Remove stores which are post-dominated.
|
||||
// 1. Remove stores which are overwritten later.
|
||||
// 2. Sink stores to post-dominating blocks.
|
||||
llvm::PostDominatorTree pdt(*m_function);
|
||||
llvm::DominatorTree dt(*m_function);
|
||||
|
||||
// Post-order indices
|
||||
std::unordered_map<llvm::BasicBlock*, usz> pois;
|
||||
{
|
||||
usz i = 0;
|
||||
for (auto* bb : llvm::post_order(m_function))
|
||||
pois[bb] = i++;
|
||||
}
|
||||
|
||||
std::vector<block_info*> block_q;
|
||||
block_q.reserve(m_blocks.size());
|
||||
for (auto& [a, b] : m_blocks)
|
||||
@ -5465,14 +5475,14 @@ public:
|
||||
block_q.emplace_back(&b);
|
||||
}
|
||||
|
||||
for (usz bi = 0; bi < block_q.size(); bi++)
|
||||
for (usz bi = 0; bi < block_q.size();)
|
||||
{
|
||||
auto bqbi = block_q[bi++];
|
||||
|
||||
// TODO: process all registers up to s_reg_max
|
||||
for (u32 i = 0; i < 128; i++)
|
||||
{
|
||||
auto& bs = block_q[bi]->store[i];
|
||||
|
||||
if (bs)
|
||||
if (auto& bs = bqbi->store[i])
|
||||
{
|
||||
for (auto& [a, b] : m_blocks)
|
||||
{
|
||||
@ -5482,17 +5492,111 @@ public:
|
||||
{
|
||||
bs->eraseFromParent();
|
||||
bs = nullptr;
|
||||
|
||||
pdt.recalculate(*m_function);
|
||||
dt.recalculate(*m_function);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bs)
|
||||
continue;
|
||||
|
||||
// Set of store instructions which overwrite bs
|
||||
std::vector<llvm::BasicBlock*> killers;
|
||||
|
||||
for (auto& [a, b] : m_blocks)
|
||||
{
|
||||
const auto si = b.store[i];
|
||||
|
||||
if (si && si != bs)
|
||||
{
|
||||
if (pois[bs->getParent()] > pois[si->getParent()])
|
||||
{
|
||||
killers.emplace_back(si->getParent());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset: store is not the first in the set
|
||||
killers.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (killers.empty())
|
||||
continue;
|
||||
|
||||
// Find nearest common post-dominator
|
||||
llvm::BasicBlock* common_pdom = killers[0];
|
||||
for (auto* bbb : llvm::drop_begin(killers))
|
||||
{
|
||||
if (!common_pdom)
|
||||
break;
|
||||
common_pdom = pdt.findNearestCommonDominator(common_pdom, bbb);
|
||||
}
|
||||
|
||||
// Shortcut
|
||||
if (!pdt.dominates(common_pdom, bs->getParent()))
|
||||
common_pdom = nullptr;
|
||||
|
||||
// Look for possibly-dead store in CFG starting from the exit nodes
|
||||
llvm::SetVector<llvm::BasicBlock*> work_list;
|
||||
if (std::count(killers.begin(), killers.end(), common_pdom) == 0)
|
||||
{
|
||||
if (common_pdom)
|
||||
{
|
||||
// Shortcut
|
||||
work_list.insert(common_pdom);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check all exits
|
||||
for (auto* r : pdt.roots())
|
||||
work_list.insert(r);
|
||||
}
|
||||
}
|
||||
|
||||
for (usz wi = 0; wi < work_list.size(); wi++)
|
||||
{
|
||||
auto* cur = work_list[wi];
|
||||
if (std::count(killers.begin(), killers.end(), cur))
|
||||
continue;
|
||||
|
||||
if (cur == bs->getParent())
|
||||
{
|
||||
// Reset: store is not dead
|
||||
killers.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto* p : llvm::predecessors(cur))
|
||||
work_list.insert(p);
|
||||
}
|
||||
|
||||
// Finally erase the dead store
|
||||
if (!killers.empty())
|
||||
{
|
||||
bs->eraseFromParent();
|
||||
bs = nullptr;
|
||||
|
||||
// Run the loop from the start
|
||||
bi = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
block_q.clear();
|
||||
for (auto& [a, b] : m_blocks)
|
||||
{
|
||||
block_q.emplace_back(&b);
|
||||
}
|
||||
|
||||
for (usz bi = 0; bi < block_q.size(); bi++)
|
||||
{
|
||||
for (u32 i = 0; i < 128; i++)
|
||||
{
|
||||
// If store isn't erased, try to sink it
|
||||
if (bs)
|
||||
if (auto& bs = block_q[bi]->store[i])
|
||||
{
|
||||
std::map<u32, block_info*, std::greater<>> sucs;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user