Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IR: Optimize runtime of optimization passes #670

Merged
merged 24 commits into from Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e847f94
RA: rework ConstrainedRAPass::CalculateNodeInterference
skmp Jan 19, 2021
77d072e
RA: Switch active set to also use BucketList
skmp Jan 19, 2021
91ddc1d
RCLSE: Optimize FindMemberInfo to be O(1)
skmp Jan 19, 2021
6380ab6
RA: Optimize register conflict handling
skmp Jan 19, 2021
af94e24
RA: Simplify and optimize data structures
skmp Jan 19, 2021
900fc6d
ConstProp: Switch maps to unordred_maps
skmp Jan 19, 2021
56ca731
DSE: Merge Flag/GPR/FPR passes for perf
skmp Jan 19, 2021
997650b
DSE: Merge logic more for perf
skmp Jan 19, 2021
6bdf785
DSE: Optimize map lookups
skmp Jan 19, 2021
f3e19ef
DSE: No need to loop to find branching op
skmp Jan 19, 2021
9c760ff
RA: Get OP_JUMP/CONDJUMP without loop in CalculatePrecessors
skmp Jan 19, 2021
10b6fb0
RA: Rename CalculatePrecessors to CalculatePredecessors
skmp Jan 19, 2021
47ee9af
ConstProp: Keep pools in heap
skmp Jan 19, 2021
c3682f9
RA: Fix several bugs, get rid of virtual registers, remove unused com…
skmp Jan 19, 2021
e7e6b66
RA: Cleanups
skmp Jan 19, 2021
a9332e6
JIT/x64: Fix VAddV
skmp Jan 19, 2021
9f3ce47
RA: Expire ending intervals before starting new ones
skmp Jan 19, 2021
d3fc85e
RA: Make spans at least 1 offset long
skmp Jan 20, 2021
8aef9cb
RA: Exit after first spill per iteration is found
skmp Jan 20, 2021
9c462eb
ConsProp: Revert to ordered set for identical codegen
skmp Jan 20, 2021
ac1036a
IR: Sync Invalid class with RA
skmp Jan 20, 2021
0e7db64
RA: Run compation after spilling, not before
skmp Jan 20, 2021
00ca576
IRCompaction: Only memset in debug
skmp Jan 21, 2021
0546da7
Address review feedback
skmp Jan 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 1 addition & 3 deletions External/FEXCore/Source/CMakeLists.txt
Expand Up @@ -155,10 +155,8 @@ set (SRCS
Interface/IR/Passes/ValueDominanceValidation.cpp
Interface/IR/Passes/PhiValidation.cpp
Interface/IR/Passes/RedundantFlagCalculationElimination.cpp
Interface/IR/Passes/DeadFlagStoreElimination.cpp
Interface/IR/Passes/DeadStoreElimination.cpp
Interface/IR/Passes/StaticRegisterAllocationPass.cpp
Interface/IR/Passes/DeadGPRStoreElimination.cpp
Interface/IR/Passes/DeadFPRStoreElimination.cpp
Interface/IR/Passes/RegisterAllocationPass.cpp
Interface/IR/Passes/SyscallOptimization.cpp
Utils/ELFLoader.cpp
Expand Down
Expand Up @@ -327,7 +327,7 @@ DEF_OP(VAddV) {
switch (Op->Header.ElementSize) {
case 2: {
for (int i = Elements; i > 1; i >>= 1) {
phaddw(Dest, Src);
vphaddw(Dest, Src, Dest);
Src = Dest;
}
pextrw(eax, Dest, 0);
Expand All @@ -336,7 +336,7 @@ DEF_OP(VAddV) {
}
case 4: {
for (int i = Elements; i > 1; i >>= 1) {
phaddd(Dest, Src);
vphaddd(Dest, Src, Dest);
Src = Dest;
}
pextrd(eax, Dest, 0);
Expand Down
2 changes: 1 addition & 1 deletion External/FEXCore/Source/Interface/IR/IR.json
Expand Up @@ -28,7 +28,7 @@
"static constexpr FEXCore::IR::RegisterClassType FPRFixedClass {3}",
"static constexpr FEXCore::IR::RegisterClassType GPRPairClass {4}",
"static constexpr FEXCore::IR::RegisterClassType ComplexClass {5}",
"static constexpr FEXCore::IR::RegisterClassType InvalidClass {~0U}",
"static constexpr FEXCore::IR::RegisterClassType InvalidClass {7}",
"",
"static const FEXCore::IR::TypeDefinition i8 {TypeDefinition::Create(1, 0)}",
"static const FEXCore::IR::TypeDefinition i16 {TypeDefinition::Create(2, 0)}",
Expand Down
4 changes: 1 addition & 3 deletions External/FEXCore/Source/Interface/IR/PassManager.cpp
Expand Up @@ -11,9 +11,7 @@ void PassManager::AddDefaultPasses(bool InlineConstants, bool StaticRegisterAllo

if (!DisablePasses()) {
InsertPass(CreateContextLoadStoreElimination());
InsertPass(CreateDeadFlagStoreElimination());
InsertPass(CreateDeadGPRStoreElimination());
InsertPass(CreateDeadFPRStoreElimination());
InsertPass(CreateDeadStoreElimination());
InsertPass(CreatePassDeadCodeElimination());
InsertPass(CreateConstProp(InlineConstants));

Expand Down
4 changes: 1 addition & 3 deletions External/FEXCore/Source/Interface/IR/Passes.h
Expand Up @@ -8,9 +8,7 @@ FEXCore::IR::Pass* CreateConstProp(bool InlineConstants);
FEXCore::IR::Pass* CreateContextLoadStoreElimination();
FEXCore::IR::Pass* CreateSyscallOptimization();
FEXCore::IR::Pass* CreateDeadFlagCalculationEliminination();
FEXCore::IR::Pass* CreateDeadFlagStoreElimination();
FEXCore::IR::Pass* CreateDeadGPRStoreElimination();
FEXCore::IR::Pass* CreateDeadFPRStoreElimination();
FEXCore::IR::Pass* CreateDeadStoreElimination();
FEXCore::IR::Pass* CreatePassDeadCodeElimination();
FEXCore::IR::Pass* CreateIRCompaction();
FEXCore::IR::RegisterAllocationPass* CreateRegisterAllocationPass(FEXCore::IR::Pass* CompactionPass, bool OptimizeSRA);
Expand Down
18 changes: 9 additions & 9 deletions External/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp
Expand Up @@ -12,6 +12,8 @@
namespace FEXCore::IR {

class ConstProp final : public FEXCore::IR::Pass {
std::unordered_map<uint64_t, OrderedNode*> ConstPool;
std::map<OrderedNode*, uint64_t> AddressgenConsts;
public:
bool Run(IREmitter *IREmit) override;
bool InlineConstants;
Expand Down Expand Up @@ -164,22 +166,21 @@ bool ConstProp::Run(IREmitter *IREmit) {
auto HeaderOp = CurrentIR.GetHeader();

{
std::map<uint64_t, OrderedNode*> Consts;

// constants are pooled per block
for (auto [BlockNode, BlockHeader] : CurrentIR.GetBlocks()) {
for (auto [CodeNode, IROp] : CurrentIR.GetCode(BlockNode)) {
if (IROp->Op == OP_CONSTANT) {
auto Op = IROp->C<IR::IROp_Constant>();
if (Consts.count(Op->Constant)) {
IREmit->ReplaceAllUsesWith(CodeNode, Consts[Op->Constant]);
if (ConstPool.count(Op->Constant)) {
IREmit->ReplaceAllUsesWith(CodeNode, ConstPool[Op->Constant]);
Changed = true;
} else {
Consts[Op->Constant] = CodeNode;
ConstPool[Op->Constant] = CodeNode;
}
}
}
Consts.clear();
ConstPool.clear();
}
}

Expand Down Expand Up @@ -265,29 +266,28 @@ bool ConstProp::Run(IREmitter *IREmit) {

// LoadMem / StoreMem imm pooling
// If imms are close by, use address gen to generate the values instead of using a new imm
std::map<OrderedNode*, uint64_t> Consts;
for (auto [BlockNode, BlockIROp] : CurrentIR.GetBlocks()) {
for (auto [CodeNode, IROp] : CurrentIR.GetCode(BlockNode)) {
if (IROp->Op == OP_LOADMEM || IROp->Op == OP_STOREMEM) {
uint64_t Addr;

if (IREmit->IsValueConstant(IROp->Args[0], &Addr) && IROp->Args[1].IsInvalid()) {
for (auto& Const: Consts) {
for (auto& Const: AddressgenConsts) {
if ((Addr - Const.second) < 65536) {
IREmit->ReplaceNodeArgument(CodeNode, 0, Const.first);
IREmit->ReplaceNodeArgument(CodeNode, 1, IREmit->_Constant(Addr - Const.second));
goto doneOp;
}
}

Consts[IREmit->UnwrapNode(IROp->Args[0])] = Addr;
AddressgenConsts[IREmit->UnwrapNode(IROp->Args[0])] = Addr;
}
doneOp:
;
}
IREmit->SetWriteCursor(CodeNode);
}
Consts.clear();
AddressgenConsts.clear();
}

for (auto [CodeNode, IROp] : CurrentIR.GetAllCode()) {
Expand Down
Expand Up @@ -28,7 +28,10 @@ namespace {
FEXCore::IR::OrderedNode *StoreNode;
};

using ContextInfo = std::vector<ContextMemberInfo>;
struct ContextInfo {
std::vector<ContextMemberInfo*> Lookup;
std::vector<ContextMemberInfo> ClassificationInfo;
};

constexpr static std::array<LastAccessType, 14> DefaultAccess = {
ACCESS_NONE,
Expand All @@ -47,7 +50,9 @@ namespace {
ACCESS_NONE,
};

static void ClassifyContextStruct(ContextInfo *ContextClassification) {
static void ClassifyContextStruct(ContextInfo *ContextClassificationInfo) {
auto ContextClassification = &ContextClassificationInfo->ClassificationInfo;

ContextClassification->emplace_back(ContextMemberInfo{
ContextMemberClassification {
offsetof(FEXCore::Core::CPUState, rip),
Expand Down Expand Up @@ -88,15 +93,6 @@ namespace {
});
}

ContextClassification->emplace_back(ContextMemberInfo{
ContextMemberClassification {
offsetof(FEXCore::Core::CPUState, gs),
sizeof(FEXCore::Core::CPUState::gs),
},
DefaultAccess[4],
FEXCore::IR::InvalidClass,
});

ContextClassification->emplace_back(ContextMemberInfo{
ContextMemberClassification {
offsetof(FEXCore::Core::CPUState, es),
Expand Down Expand Up @@ -133,6 +129,15 @@ namespace {
FEXCore::IR::InvalidClass,
});

ContextClassification->emplace_back(ContextMemberInfo{
ContextMemberClassification {
offsetof(FEXCore::Core::CPUState, gs),
sizeof(FEXCore::Core::CPUState::gs),
},
DefaultAccess[4],
FEXCore::IR::InvalidClass,
});

ContextClassification->emplace_back(ContextMemberInfo{
ContextMemberClassification {
offsetof(FEXCore::Core::CPUState, fs),
Expand Down Expand Up @@ -186,16 +191,27 @@ namespace {
}

size_t ClassifiedStructSize{};
ContextClassificationInfo->Lookup.reserve(sizeof(FEXCore::Core::CPUState));
for (auto &it : *ContextClassification) {
LogMan::Throw::A(it.Class.Offset == ContextClassificationInfo->Lookup.size(), "Offset missmatch %d %d", it.Class.Offset == ContextClassificationInfo->Lookup.size());
for (int i = 0; i < it.Class.Size; i++) {
ContextClassificationInfo->Lookup.push_back(&it);
}
ClassifiedStructSize += it.Class.Size;
}

LogMan::Throw::A(ClassifiedStructSize == sizeof(FEXCore::Core::CPUState),
"Classified CPUStruct size doesn't match real CPUState struct size! %ld != %ld",
ClassifiedStructSize, sizeof(FEXCore::Core::CPUState));

LogMan::Throw::A(ContextClassificationInfo->Lookup.size() == sizeof(FEXCore::Core::CPUState),
"Classified CPUStruct size doesn't match real CPUState struct size! %ld != %ld",
ContextClassificationInfo->Lookup.size(), sizeof(FEXCore::Core::CPUState));
}

static void ResetClassificationAccesses(ContextInfo *ContextClassification) {
static void ResetClassificationAccesses(ContextInfo *ContextClassificationInfo) {
auto ContextClassification = &ContextClassificationInfo->ClassificationInfo;

auto SetAccess = [&](size_t Offset, auto Access) {
ContextClassification->at(Offset).Accessed = Access;
ContextClassification->at(Offset).AccessRegClass = FEXCore::IR::InvalidClass;
Expand Down Expand Up @@ -265,20 +281,8 @@ class RCLSE final : public FEXCore::IR::Pass {
bool RedundantStoreLoadElimination(FEXCore::IR::IREmitter *IREmit);
};

ContextMemberInfo *RCLSE::FindMemberInfo(ContextInfo *ClassifiedInfo, uint32_t Offset, uint8_t Size) {
ContextMemberInfo *Info{};
// Just linearly scan to find the info
for (size_t i = 0; i < ClassifiedInfo->size(); ++i) {
ContextMemberInfo *LocalInfo = &ClassifiedInfo->at(i);
if (LocalInfo->Class.Offset <= Offset &&
(LocalInfo->Class.Offset + LocalInfo->Class.Size) > Offset) {
Info = LocalInfo;
break;
}
}
LogMan::Throw::A(Info != nullptr, "Couldn't find Context Member to record to");

return Info;
ContextMemberInfo *RCLSE::FindMemberInfo(ContextInfo *ContextClassificationInfo, uint32_t Offset, uint8_t Size) {
return ContextClassificationInfo->Lookup.at(Offset);
}

ContextMemberInfo *RCLSE::RecordAccess(ContextMemberInfo *Info, FEXCore::IR::RegisterClassType RegClass, uint32_t Offset, uint8_t Size, LastAccessType AccessType, FEXCore::IR::OrderedNode *Node, FEXCore::IR::OrderedNode *StoreNode) {
Expand Down Expand Up @@ -404,7 +408,7 @@ bool RCLSE::RedundantStoreLoadElimination(FEXCore::IR::IREmitter *IREmit) {

// XXX: Walk the list and calculate the control flow

ContextInfo LocalInfo = ClassifiedStruct;
ContextInfo &LocalInfo = ClassifiedStruct;

for (auto [BlockNode, BlockHeader] : CurrentIR.GetBlocks()) {

Expand Down