reg_alloc: Fix cast-qual issue

This commit is contained in:
Merry 2023-01-31 15:10:51 +00:00
parent 60030a76d7
commit d796d8e93d
20 changed files with 101 additions and 56 deletions

View file

@ -86,6 +86,7 @@ add_library(dynarmic
ir/opt/dead_code_elimination_pass.cpp ir/opt/dead_code_elimination_pass.cpp
ir/opt/identity_removal_pass.cpp ir/opt/identity_removal_pass.cpp
ir/opt/ir_matcher.h ir/opt/ir_matcher.h
ir/opt/naming_pass.cpp
ir/opt/passes.h ir/opt/passes.h
ir/opt/polyfill_pass.cpp ir/opt/polyfill_pass.cpp
ir/opt/verification_pass.cpp ir/opt/verification_pass.cpp

View file

@ -165,6 +165,7 @@ IR::Block A32AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const {
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
Optimization::PolyfillPass(ir_block, {}); Optimization::PolyfillPass(ir_block, {});
Optimization::NamingPass(ir_block);
if (conf.HasOptimization(OptimizationFlag::GetSetElimination)) { if (conf.HasOptimization(OptimizationFlag::GetSetElimination)) {
Optimization::A32GetSetElimination(ir_block, {.convert_nzc_to_nz = true}); Optimization::A32GetSetElimination(ir_block, {.convert_nzc_to_nz = true});
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);

View file

@ -333,6 +333,7 @@ IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const {
{conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
Optimization::A64CallbackConfigPass(ir_block, conf); Optimization::A64CallbackConfigPass(ir_block, conf);
Optimization::NamingPass(ir_block);
if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) { if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) {
Optimization::A64GetSetElimination(ir_block); Optimization::A64GetSetElimination(ir_block);
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);

View file

@ -491,8 +491,7 @@ std::optional<DoNotFastmemMarker> ShouldFastmem(EmitContext& ctx, IR::Inst* inst
return std::nullopt; return std::nullopt;
} }
const auto inst_offset = std::distance(ctx.block.begin(), IR::Block::iterator(inst)); const auto marker = std::make_tuple(ctx.block.Location(), inst->GetName());
const auto marker = std::make_tuple(ctx.block.Location(), inst_offset);
if (ctx.fastmem.ShouldFastmem(marker)) { if (ctx.fastmem.ShouldFastmem(marker)) {
return marker; return marker;
} }

View file

@ -17,7 +17,7 @@
namespace Dynarmic::Backend::Arm64 { namespace Dynarmic::Backend::Arm64 {
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, std::ptrdiff_t>; using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
struct DoNotFastmemMarkerHash { struct DoNotFastmemMarkerHash {
size_t operator()(const DoNotFastmemMarker& value) const { size_t operator()(const DoNotFastmemMarker& value) const {

View file

@ -336,7 +336,7 @@ private:
mutable std::mt19937 rand_gen; mutable std::mt19937 rand_gen;
tsl::robin_set<IR::Inst*> defined_insts; tsl::robin_set<const IR::Inst*> defined_insts;
}; };
template<typename T> template<typename T>

View file

@ -97,7 +97,7 @@ protected:
std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const override; std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const override;
// Fastmem information // Fastmem information
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, std::ptrdiff_t>; using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
struct FastmemPatchInfo { struct FastmemPatchInfo {
u64 resume_rip; u64 resume_rip;
u64 callback; u64 callback;

View file

@ -174,6 +174,7 @@ private:
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
Optimization::PolyfillPass(ir_block, polyfill_options); Optimization::PolyfillPass(ir_block, polyfill_options);
Optimization::NamingPass(ir_block);
if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) { if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) {
Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true}); Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true});
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);
@ -197,7 +198,9 @@ Jit::~Jit() = default;
HaltReason Jit::Run() { HaltReason Jit::Run() {
ASSERT(!is_executing); ASSERT(!is_executing);
is_executing = true; is_executing = true;
SCOPE_EXIT { this->is_executing = false; }; SCOPE_EXIT {
this->is_executing = false;
};
const HaltReason hr = impl->Execute(); const HaltReason hr = impl->Execute();
@ -209,7 +212,9 @@ HaltReason Jit::Run() {
HaltReason Jit::Step() { HaltReason Jit::Step() {
ASSERT(!is_executing); ASSERT(!is_executing);
is_executing = true; is_executing = true;
SCOPE_EXIT { this->is_executing = false; }; SCOPE_EXIT {
this->is_executing = false;
};
const HaltReason hr = impl->Step(); const HaltReason hr = impl->Step();

View file

@ -95,7 +95,7 @@ protected:
std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const override; std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const override;
// Fastmem information // Fastmem information
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, std::ptrdiff_t>; using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
struct FastmemPatchInfo { struct FastmemPatchInfo {
u64 resume_rip; u64 resume_rip;
u64 callback; u64 callback;

View file

@ -72,7 +72,9 @@ public:
PerformRequestedCacheInvalidation(); PerformRequestedCacheInvalidation();
is_executing = true; is_executing = true;
SCOPE_EXIT { this->is_executing = false; }; SCOPE_EXIT {
this->is_executing = false;
};
// TODO: Check code alignment // TODO: Check code alignment
@ -99,7 +101,9 @@ public:
PerformRequestedCacheInvalidation(); PerformRequestedCacheInvalidation();
is_executing = true; is_executing = true;
SCOPE_EXIT { this->is_executing = false; }; SCOPE_EXIT {
this->is_executing = false;
};
const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep());
@ -273,6 +277,7 @@ private:
{conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
Optimization::PolyfillPass(ir_block, polyfill_options); Optimization::PolyfillPass(ir_block, polyfill_options);
Optimization::A64CallbackConfigPass(ir_block, conf); Optimization::A64CallbackConfigPass(ir_block, conf);
Optimization::NamingPass(ir_block);
if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) { if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) {
Optimization::A64GetSetElimination(ir_block); Optimization::A64GetSetElimination(ir_block);
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);

View file

@ -35,10 +35,6 @@ EmitContext::EmitContext(RegAlloc& reg_alloc, IR::Block& block)
EmitContext::~EmitContext() = default; EmitContext::~EmitContext() = default;
size_t EmitContext::GetInstOffset(IR::Inst* inst) const {
return static_cast<size_t>(std::distance(block.begin(), IR::Block::iterator(inst)));
}
void EmitContext::EraseInstruction(IR::Inst* inst) { void EmitContext::EraseInstruction(IR::Inst* inst) {
block.Instructions().erase(inst); block.Instructions().erase(inst);
inst->ClearArgs(); inst->ClearArgs();

View file

@ -53,7 +53,6 @@ struct EmitContext {
EmitContext(RegAlloc& reg_alloc, IR::Block& block); EmitContext(RegAlloc& reg_alloc, IR::Block& block);
virtual ~EmitContext(); virtual ~EmitContext();
size_t GetInstOffset(IR::Inst* inst) const;
void EraseInstruction(IR::Inst* inst); void EraseInstruction(IR::Inst* inst);
virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0; virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0;

View file

@ -19,7 +19,7 @@ std::optional<AxxEmitX64::DoNotFastmemMarker> AxxEmitX64::ShouldFastmem(AxxEmitC
return std::nullopt; return std::nullopt;
} }
const auto marker = std::make_tuple(ctx.Location(), ctx.GetInstOffset(inst)); const auto marker = std::make_tuple(ctx.Location(), inst->GetName());
if (do_not_fastmem.count(marker) > 0) { if (do_not_fastmem.count(marker) > 0) {
return std::nullopt; return std::nullopt;
} }

View file

@ -168,17 +168,14 @@ std::string DumpBlock(const IR::Block& block) {
} }
ret += '\n'; ret += '\n';
std::map<const IR::Inst*, size_t> inst_to_index; const auto arg_to_string = [](const IR::Value& arg) -> std::string {
size_t index = 0;
const auto arg_to_string = [&inst_to_index](const IR::Value& arg) -> std::string {
if (arg.IsEmpty()) { if (arg.IsEmpty()) {
return "<null>"; return "<null>";
} else if (!arg.IsImmediate()) { } else if (!arg.IsImmediate()) {
if (const auto iter = inst_to_index.find(arg.GetInst()); iter != inst_to_index.end()) { if (const unsigned name = arg.GetInst()->GetName()) {
return fmt::format("%{}", iter->second); return fmt::format("%{}", name);
} }
return fmt::format("%<unknown inst {:016x}>", reinterpret_cast<u64>(arg.GetInst())); return fmt::format("%<unnamed inst {:016x}>", reinterpret_cast<u64>(arg.GetInst()));
} }
switch (arg.GetType()) { switch (arg.GetType()) {
case Type::U1: case Type::U1:
@ -209,7 +206,11 @@ std::string DumpBlock(const IR::Block& block) {
ret += fmt::format("[{:016x}] ", reinterpret_cast<u64>(&inst)); ret += fmt::format("[{:016x}] ", reinterpret_cast<u64>(&inst));
if (GetTypeOf(op) != Type::Void) { if (GetTypeOf(op) != Type::Void) {
ret += fmt::format("%{:<5} = ", index); if (inst.GetName()) {
ret += fmt::format("%{:<5} = ", inst.GetName());
} else {
ret += "noname = ";
}
} else { } else {
ret += " "; // '%00000 = ' -> 1 + 5 + 3 = 9 spaces ret += " "; // '%00000 = ' -> 1 + 5 + 3 = 9 spaces
} }
@ -233,7 +234,6 @@ std::string DumpBlock(const IR::Block& block) {
ret += fmt::format(" (uses: {})", inst.UseCount()); ret += fmt::format(" (uses: {})", inst.UseCount());
ret += '\n'; ret += '\n';
inst_to_index[&inst] = index++;
} }
ret += "terminal = " + TerminalToString(block.GetTerminal()) + '\n'; ret += "terminal = " + TerminalToString(block.GetTerminal()) + '\n';

View file

@ -141,12 +141,18 @@ public:
void ReplaceUsesWith(Value replacement); void ReplaceUsesWith(Value replacement);
// IR name (i.e. instruction number in block). This is set in the naming pass. Treat 0 as an invalid name.
// This is used for debugging and fastmem instruction identification.
void SetName(unsigned value) { name = value; }
unsigned GetName() const { return name; }
private: private:
void Use(const Value& value); void Use(const Value& value);
void UndoUse(const Value& value); void UndoUse(const Value& value);
Opcode op; Opcode op;
size_t use_count = 0; unsigned use_count = 0;
unsigned name = 0;
std::array<Value, max_arg_count> args; std::array<Value, max_arg_count> args;
// Linked list of pseudooperations associated with this instruction. // Linked list of pseudooperations associated with this instruction.

View file

@ -0,0 +1,18 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2023 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/microinstruction.h"
namespace Dynarmic::Optimization {
void NamingPass(IR::Block& block) {
unsigned name = 1;
for (auto& inst : block) {
inst.SetName(name++);
}
}
} // namespace Dynarmic::Optimization

View file

@ -42,5 +42,6 @@ void ConstantPropagation(IR::Block& block);
void DeadCodeElimination(IR::Block& block); void DeadCodeElimination(IR::Block& block);
void IdentityRemovalPass(IR::Block& block); void IdentityRemovalPass(IR::Block& block);
void VerificationPass(const IR::Block& block); void VerificationPass(const IR::Block& block);
void NamingPass(IR::Block& block);
} // namespace Dynarmic::Optimization } // namespace Dynarmic::Optimization

View file

@ -176,6 +176,7 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32Unicorn<Th
while (num_insts < instructions_to_execute_count) { while (num_insts < instructions_to_execute_count) {
A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, A32::FPSCR{}}; A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, A32::FPSCR{}};
IR::Block ir_block = A32::Translate(descriptor, &test_env, {}); IR::Block ir_block = A32::Translate(descriptor, &test_env, {});
Optimization::NamingPass(ir_block);
Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true}); Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true});
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);
Optimization::A32ConstantMemoryReads(ir_block, &test_env); Optimization::A32ConstantMemoryReads(ir_block, &test_env);

View file

@ -265,6 +265,8 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv
const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); }; const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); };
IR::Block ir_block = A64::Translate({instructions_start, FP::FPCR{fpcr}}, get_code, {}); IR::Block ir_block = A64::Translate({instructions_start, FP::FPCR{fpcr}}, get_code, {});
Optimization::A64CallbackConfigPass(ir_block, GetUserConfig(jit_env)); Optimization::A64CallbackConfigPass(ir_block, GetUserConfig(jit_env));
Optimization::NamingPass(ir_block);
fmt::print("IR:\n"); fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block)); fmt::print("{}\n", IR::DumpBlock(ir_block));
@ -272,6 +274,7 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);
Optimization::ConstantPropagation(ir_block); Optimization::ConstantPropagation(ir_block);
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);
fmt::print("Optimized IR:\n"); fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block)); fmt::print("{}\n", IR::DumpBlock(ir_block));

View file

@ -58,20 +58,23 @@ void PrintA32Instruction(u32 instruction) {
fmt::print("Name: {}\n", GetNameOfA32Instruction(instruction)); fmt::print("Name: {}\n", GetNameOfA32Instruction(instruction));
const A32::LocationDescriptor location{0, {}, {}}; const A32::LocationDescriptor location{0, {}, {}};
IR::Block block{location}; IR::Block ir_block{location};
const bool should_continue = A32::TranslateSingleInstruction(block, location, instruction); const bool should_continue = A32::TranslateSingleInstruction(ir_block, location, instruction);
fmt::print("should_continue: {}\n\n", should_continue); fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(block));
Optimization::A32GetSetElimination(block, {}); Optimization::NamingPass(ir_block);
Optimization::DeadCodeElimination(block);
Optimization::ConstantPropagation(block); fmt::print("IR:\n");
Optimization::DeadCodeElimination(block); fmt::print("{}\n", IR::DumpBlock(ir_block));
Optimization::IdentityRemovalPass(block);
Optimization::A32GetSetElimination(ir_block, {});
Optimization::DeadCodeElimination(ir_block);
Optimization::ConstantPropagation(ir_block);
Optimization::DeadCodeElimination(ir_block);
Optimization::IdentityRemovalPass(ir_block);
fmt::print("Optimized IR:\n"); fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(block)); fmt::print("{}\n", IR::DumpBlock(ir_block));
} }
void PrintA64Instruction(u32 instruction) { void PrintA64Instruction(u32 instruction) {
@ -79,20 +82,23 @@ void PrintA64Instruction(u32 instruction) {
fmt::print("Name: {}\n", GetNameOfA64Instruction(instruction)); fmt::print("Name: {}\n", GetNameOfA64Instruction(instruction));
const A64::LocationDescriptor location{0, {}}; const A64::LocationDescriptor location{0, {}};
IR::Block block{location}; IR::Block ir_block{location};
const bool should_continue = A64::TranslateSingleInstruction(block, location, instruction); const bool should_continue = A64::TranslateSingleInstruction(ir_block, location, instruction);
fmt::print("should_continue: {}\n\n", should_continue); fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(block));
Optimization::A64GetSetElimination(block); Optimization::NamingPass(ir_block);
Optimization::DeadCodeElimination(block);
Optimization::ConstantPropagation(block); fmt::print("IR:\n");
Optimization::DeadCodeElimination(block); fmt::print("{}\n", IR::DumpBlock(ir_block));
Optimization::IdentityRemovalPass(block);
Optimization::A64GetSetElimination(ir_block);
Optimization::DeadCodeElimination(ir_block);
Optimization::ConstantPropagation(ir_block);
Optimization::DeadCodeElimination(ir_block);
Optimization::IdentityRemovalPass(ir_block);
fmt::print("Optimized IR:\n"); fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(block)); fmt::print("{}\n", IR::DumpBlock(ir_block));
} }
void PrintThumbInstruction(u32 instruction) { void PrintThumbInstruction(u32 instruction) {
@ -103,20 +109,23 @@ void PrintThumbInstruction(u32 instruction) {
fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch32(true, 0, (u8*)&instruction, inst_size)); fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch32(true, 0, (u8*)&instruction, inst_size));
const A32::LocationDescriptor location{0, A32::PSR{0x1F0}, {}}; const A32::LocationDescriptor location{0, A32::PSR{0x1F0}, {}};
IR::Block block{location}; IR::Block ir_block{location};
const bool should_continue = A32::TranslateSingleInstruction(block, location, instruction); const bool should_continue = A32::TranslateSingleInstruction(ir_block, location, instruction);
fmt::print("should_continue: {}\n\n", should_continue); fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(block));
Optimization::A32GetSetElimination(block, {}); Optimization::NamingPass(ir_block);
Optimization::DeadCodeElimination(block);
Optimization::ConstantPropagation(block); fmt::print("IR:\n");
Optimization::DeadCodeElimination(block); fmt::print("{}\n", IR::DumpBlock(ir_block));
Optimization::IdentityRemovalPass(block);
Optimization::A32GetSetElimination(ir_block, {});
Optimization::DeadCodeElimination(ir_block);
Optimization::ConstantPropagation(ir_block);
Optimization::DeadCodeElimination(ir_block);
Optimization::IdentityRemovalPass(ir_block);
fmt::print("Optimized IR:\n"); fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(block)); fmt::print("{}\n", IR::DumpBlock(ir_block));
} }
class ExecEnv final : public Dynarmic::A32::UserCallbacks { class ExecEnv final : public Dynarmic::A32::UserCallbacks {