reg_alloc: Fix cast-qual issue
This commit is contained in:
parent
60030a76d7
commit
d796d8e93d
20 changed files with 101 additions and 56 deletions
|
@ -86,6 +86,7 @@ add_library(dynarmic
|
|||
ir/opt/dead_code_elimination_pass.cpp
|
||||
ir/opt/identity_removal_pass.cpp
|
||||
ir/opt/ir_matcher.h
|
||||
ir/opt/naming_pass.cpp
|
||||
ir/opt/passes.h
|
||||
ir/opt/polyfill_pass.cpp
|
||||
ir/opt/verification_pass.cpp
|
||||
|
|
|
@ -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});
|
||||
|
||||
Optimization::PolyfillPass(ir_block, {});
|
||||
Optimization::NamingPass(ir_block);
|
||||
if (conf.HasOptimization(OptimizationFlag::GetSetElimination)) {
|
||||
Optimization::A32GetSetElimination(ir_block, {.convert_nzc_to_nz = true});
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
|
|
|
@ -333,6 +333,7 @@ IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const {
|
|||
{conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
|
||||
|
||||
Optimization::A64CallbackConfigPass(ir_block, conf);
|
||||
Optimization::NamingPass(ir_block);
|
||||
if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) {
|
||||
Optimization::A64GetSetElimination(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
|
|
|
@ -491,8 +491,7 @@ std::optional<DoNotFastmemMarker> ShouldFastmem(EmitContext& ctx, IR::Inst* inst
|
|||
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_offset);
|
||||
const auto marker = std::make_tuple(ctx.block.Location(), inst->GetName());
|
||||
if (ctx.fastmem.ShouldFastmem(marker)) {
|
||||
return marker;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
namespace Dynarmic::Backend::Arm64 {
|
||||
|
||||
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, std::ptrdiff_t>;
|
||||
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
|
||||
|
||||
struct DoNotFastmemMarkerHash {
|
||||
size_t operator()(const DoNotFastmemMarker& value) const {
|
||||
|
|
|
@ -336,7 +336,7 @@ private:
|
|||
|
||||
mutable std::mt19937 rand_gen;
|
||||
|
||||
tsl::robin_set<IR::Inst*> defined_insts;
|
||||
tsl::robin_set<const IR::Inst*> defined_insts;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -97,7 +97,7 @@ protected:
|
|||
std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const override;
|
||||
|
||||
// Fastmem information
|
||||
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, std::ptrdiff_t>;
|
||||
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
|
||||
struct FastmemPatchInfo {
|
||||
u64 resume_rip;
|
||||
u64 callback;
|
||||
|
|
|
@ -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});
|
||||
Optimization::PolyfillPass(ir_block, polyfill_options);
|
||||
Optimization::NamingPass(ir_block);
|
||||
if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) {
|
||||
Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true});
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
|
@ -197,7 +198,9 @@ Jit::~Jit() = default;
|
|||
HaltReason Jit::Run() {
|
||||
ASSERT(!is_executing);
|
||||
is_executing = true;
|
||||
SCOPE_EXIT { this->is_executing = false; };
|
||||
SCOPE_EXIT {
|
||||
this->is_executing = false;
|
||||
};
|
||||
|
||||
const HaltReason hr = impl->Execute();
|
||||
|
||||
|
@ -209,7 +212,9 @@ HaltReason Jit::Run() {
|
|||
HaltReason Jit::Step() {
|
||||
ASSERT(!is_executing);
|
||||
is_executing = true;
|
||||
SCOPE_EXIT { this->is_executing = false; };
|
||||
SCOPE_EXIT {
|
||||
this->is_executing = false;
|
||||
};
|
||||
|
||||
const HaltReason hr = impl->Step();
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ protected:
|
|||
std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const override;
|
||||
|
||||
// Fastmem information
|
||||
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, std::ptrdiff_t>;
|
||||
using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
|
||||
struct FastmemPatchInfo {
|
||||
u64 resume_rip;
|
||||
u64 callback;
|
||||
|
|
|
@ -72,7 +72,9 @@ public:
|
|||
PerformRequestedCacheInvalidation();
|
||||
|
||||
is_executing = true;
|
||||
SCOPE_EXIT { this->is_executing = false; };
|
||||
SCOPE_EXIT {
|
||||
this->is_executing = false;
|
||||
};
|
||||
|
||||
// TODO: Check code alignment
|
||||
|
||||
|
@ -99,7 +101,9 @@ public:
|
|||
PerformRequestedCacheInvalidation();
|
||||
|
||||
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());
|
||||
|
||||
|
@ -273,6 +277,7 @@ private:
|
|||
{conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
|
||||
Optimization::PolyfillPass(ir_block, polyfill_options);
|
||||
Optimization::A64CallbackConfigPass(ir_block, conf);
|
||||
Optimization::NamingPass(ir_block);
|
||||
if (conf.HasOptimization(OptimizationFlag::GetSetElimination) && !conf.check_halt_on_memory_access) {
|
||||
Optimization::A64GetSetElimination(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
|
|
|
@ -35,10 +35,6 @@ EmitContext::EmitContext(RegAlloc& reg_alloc, IR::Block& block)
|
|||
|
||||
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) {
|
||||
block.Instructions().erase(inst);
|
||||
inst->ClearArgs();
|
||||
|
|
|
@ -53,7 +53,6 @@ struct EmitContext {
|
|||
EmitContext(RegAlloc& reg_alloc, IR::Block& block);
|
||||
virtual ~EmitContext();
|
||||
|
||||
size_t GetInstOffset(IR::Inst* inst) const;
|
||||
void EraseInstruction(IR::Inst* inst);
|
||||
|
||||
virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0;
|
||||
|
|
|
@ -19,7 +19,7 @@ std::optional<AxxEmitX64::DoNotFastmemMarker> AxxEmitX64::ShouldFastmem(AxxEmitC
|
|||
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) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
|
@ -168,17 +168,14 @@ std::string DumpBlock(const IR::Block& block) {
|
|||
}
|
||||
ret += '\n';
|
||||
|
||||
std::map<const IR::Inst*, size_t> inst_to_index;
|
||||
size_t index = 0;
|
||||
|
||||
const auto arg_to_string = [&inst_to_index](const IR::Value& arg) -> std::string {
|
||||
const auto arg_to_string = [](const IR::Value& arg) -> std::string {
|
||||
if (arg.IsEmpty()) {
|
||||
return "<null>";
|
||||
} else if (!arg.IsImmediate()) {
|
||||
if (const auto iter = inst_to_index.find(arg.GetInst()); iter != inst_to_index.end()) {
|
||||
return fmt::format("%{}", iter->second);
|
||||
if (const unsigned name = arg.GetInst()->GetName()) {
|
||||
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()) {
|
||||
case Type::U1:
|
||||
|
@ -209,7 +206,11 @@ std::string DumpBlock(const IR::Block& block) {
|
|||
|
||||
ret += fmt::format("[{:016x}] ", reinterpret_cast<u64>(&inst));
|
||||
if (GetTypeOf(op) != Type::Void) {
|
||||
ret += fmt::format("%{:<5} = ", index);
|
||||
if (inst.GetName()) {
|
||||
ret += fmt::format("%{:<5} = ", inst.GetName());
|
||||
} else {
|
||||
ret += "noname = ";
|
||||
}
|
||||
} else {
|
||||
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 += '\n';
|
||||
inst_to_index[&inst] = index++;
|
||||
}
|
||||
|
||||
ret += "terminal = " + TerminalToString(block.GetTerminal()) + '\n';
|
||||
|
|
|
@ -141,12 +141,18 @@ public:
|
|||
|
||||
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:
|
||||
void Use(const Value& value);
|
||||
void UndoUse(const Value& value);
|
||||
|
||||
Opcode op;
|
||||
size_t use_count = 0;
|
||||
unsigned use_count = 0;
|
||||
unsigned name = 0;
|
||||
std::array<Value, max_arg_count> args;
|
||||
|
||||
// Linked list of pseudooperations associated with this instruction.
|
||||
|
|
18
src/dynarmic/ir/opt/naming_pass.cpp
Normal file
18
src/dynarmic/ir/opt/naming_pass.cpp
Normal 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
|
|
@ -42,5 +42,6 @@ void ConstantPropagation(IR::Block& block);
|
|||
void DeadCodeElimination(IR::Block& block);
|
||||
void IdentityRemovalPass(IR::Block& block);
|
||||
void VerificationPass(const IR::Block& block);
|
||||
void NamingPass(IR::Block& block);
|
||||
|
||||
} // namespace Dynarmic::Optimization
|
||||
|
|
|
@ -176,6 +176,7 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32Unicorn<Th
|
|||
while (num_insts < instructions_to_execute_count) {
|
||||
A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, A32::FPSCR{}};
|
||||
IR::Block ir_block = A32::Translate(descriptor, &test_env, {});
|
||||
Optimization::NamingPass(ir_block);
|
||||
Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true});
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
Optimization::A32ConstantMemoryReads(ir_block, &test_env);
|
||||
|
|
|
@ -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); };
|
||||
IR::Block ir_block = A64::Translate({instructions_start, FP::FPCR{fpcr}}, get_code, {});
|
||||
Optimization::A64CallbackConfigPass(ir_block, GetUserConfig(jit_env));
|
||||
Optimization::NamingPass(ir_block);
|
||||
|
||||
fmt::print("IR:\n");
|
||||
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::ConstantPropagation(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
|
||||
fmt::print("Optimized IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
|
||||
|
|
|
@ -58,20 +58,23 @@ void PrintA32Instruction(u32 instruction) {
|
|||
fmt::print("Name: {}\n", GetNameOfA32Instruction(instruction));
|
||||
|
||||
const A32::LocationDescriptor location{0, {}, {}};
|
||||
IR::Block block{location};
|
||||
const bool should_continue = A32::TranslateSingleInstruction(block, location, instruction);
|
||||
IR::Block ir_block{location};
|
||||
const bool should_continue = A32::TranslateSingleInstruction(ir_block, location, instruction);
|
||||
fmt::print("should_continue: {}\n\n", should_continue);
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(block));
|
||||
|
||||
Optimization::A32GetSetElimination(block, {});
|
||||
Optimization::DeadCodeElimination(block);
|
||||
Optimization::ConstantPropagation(block);
|
||||
Optimization::DeadCodeElimination(block);
|
||||
Optimization::IdentityRemovalPass(block);
|
||||
Optimization::NamingPass(ir_block);
|
||||
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_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("{}\n", IR::DumpBlock(block));
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
}
|
||||
|
||||
void PrintA64Instruction(u32 instruction) {
|
||||
|
@ -79,20 +82,23 @@ void PrintA64Instruction(u32 instruction) {
|
|||
fmt::print("Name: {}\n", GetNameOfA64Instruction(instruction));
|
||||
|
||||
const A64::LocationDescriptor location{0, {}};
|
||||
IR::Block block{location};
|
||||
const bool should_continue = A64::TranslateSingleInstruction(block, location, instruction);
|
||||
IR::Block ir_block{location};
|
||||
const bool should_continue = A64::TranslateSingleInstruction(ir_block, location, instruction);
|
||||
fmt::print("should_continue: {}\n\n", should_continue);
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(block));
|
||||
|
||||
Optimization::A64GetSetElimination(block);
|
||||
Optimization::DeadCodeElimination(block);
|
||||
Optimization::ConstantPropagation(block);
|
||||
Optimization::DeadCodeElimination(block);
|
||||
Optimization::IdentityRemovalPass(block);
|
||||
Optimization::NamingPass(ir_block);
|
||||
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_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("{}\n", IR::DumpBlock(block));
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
const A32::LocationDescriptor location{0, A32::PSR{0x1F0}, {}};
|
||||
IR::Block block{location};
|
||||
const bool should_continue = A32::TranslateSingleInstruction(block, location, instruction);
|
||||
IR::Block ir_block{location};
|
||||
const bool should_continue = A32::TranslateSingleInstruction(ir_block, location, instruction);
|
||||
fmt::print("should_continue: {}\n\n", should_continue);
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(block));
|
||||
|
||||
Optimization::A32GetSetElimination(block, {});
|
||||
Optimization::DeadCodeElimination(block);
|
||||
Optimization::ConstantPropagation(block);
|
||||
Optimization::DeadCodeElimination(block);
|
||||
Optimization::IdentityRemovalPass(block);
|
||||
Optimization::NamingPass(ir_block);
|
||||
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_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("{}\n", IR::DumpBlock(block));
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
}
|
||||
|
||||
class ExecEnv final : public Dynarmic::A32::UserCallbacks {
|
||||
|
|
Loading…
Reference in a new issue