aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrueter <crueter@eden-emu.dev>2026-02-24 19:34:34 +0100
committercrueter <crueter@eden-emu.dev>2026-02-24 19:34:34 +0100
commit270232e8d6ac32fb41bdc95b17b95b6e35df4b22 (patch)
tree6849e155c2ed431694498848c7b653a2e74a63f1 /src
parentd2bef2731cea600c49f1dfc6f0f34b81bc49c511 (diff)
[dynarmic] Revert "Transition IR::Block to use stable_vector<Inst>, remove inline pool + pooled vector, remove unused mutable get/set block functors (#3543)" (#3625)
This reverts commit d64f7dfe5c3f727939b36d92600fe04f11b0f4d0. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3625
Diffstat (limited to 'src')
-rw-r--r--src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp4
-rw-r--r--src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp2
-rw-r--r--src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp4
-rw-r--r--src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp2
-rw-r--r--src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp4
-rw-r--r--src/dynarmic/src/dynarmic/frontend/A32/translate/translate_arm.cpp4
-rw-r--r--src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp4
-rw-r--r--src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp4
-rw-r--r--src/dynarmic/src/dynarmic/frontend/A64/translate/impl/system.cpp2
-rw-r--r--src/dynarmic/src/dynarmic/ir/basic_block.cpp32
-rw-r--r--src/dynarmic/src/dynarmic/ir/basic_block.h47
-rw-r--r--src/dynarmic/src/dynarmic/ir/ir_emitter.h17
-rw-r--r--src/dynarmic/src/dynarmic/ir/microinstruction.h6
-rw-r--r--src/dynarmic/src/dynarmic/ir/opt_passes.cpp27
14 files changed, 108 insertions, 51 deletions
diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp
index e4958eb67f..104d0a452c 100644
--- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp
+++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp
@@ -212,7 +212,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
oaknut::Label pass;
pass = conf.emit_cond(code, ctx, ctx.block.GetCondition());
- EmitAddCycles(code, ctx, ctx.block.cond_failed_cycle_count);
+ EmitAddCycles(code, ctx, ctx.block.ConditionFailedCycleCount());
conf.emit_condition_failed_terminal(code, ctx);
code.l(pass);
@@ -254,7 +254,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
reg_alloc.AssertNoMoreUses();
- EmitAddCycles(code, ctx, block.cycle_count);
+ EmitAddCycles(code, ctx, block.CycleCount());
conf.emit_terminal(code, ctx);
code.BRK(0);
diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp
index 32a26de781..50cbaf9526 100644
--- a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp
+++ b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp
@@ -151,7 +151,7 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, IR::Block block, const EmitCon
reg_alloc.AssertNoMoreUses();
if (emit_conf.enable_cycle_counting) {
- const size_t cycles_to_add = block.cycle_count;
+ const size_t cycles_to_add = block.CycleCount();
as.LD(Xscratch0, offsetof(StackLayout, cycles_remaining), sp);
if (mcl::bit::sign_extend<12>(-cycles_to_add) == -cycles_to_add) {
as.ADDI(Xscratch0, Xscratch0, -cycles_to_add);
diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
index 59d0bc13c4..38cec7c750 100644
--- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
+++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
@@ -148,7 +148,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
reg_alloc.AssertNoMoreUses();
if (conf.enable_cycle_counting) {
- EmitAddCycles(block.cycle_count);
+ EmitAddCycles(block.CycleCount());
}
EmitTerminal(block.GetTerminal(), ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
code.int3();
@@ -192,7 +192,7 @@ void A32EmitX64::EmitCondPrelude(const A32EmitContext& ctx) {
Xbyak::Label pass = EmitCond(ctx.block.GetCondition());
if (conf.enable_cycle_counting) {
- EmitAddCycles(ctx.block.cond_failed_cycle_count);
+ EmitAddCycles(ctx.block.ConditionFailedCycleCount());
}
EmitTerminal(IR::Term::LinkBlock{ctx.block.ConditionFailedLocation()}, ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
code.L(pass);
diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
index 825ff6f9cf..ff82d8b05c 100644
--- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
+++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
@@ -142,7 +142,7 @@ finish_this_inst:
reg_alloc.AssertNoMoreUses();
if (conf.enable_cycle_counting) {
- EmitAddCycles(block.cycle_count);
+ EmitAddCycles(block.CycleCount());
}
EmitTerminal(block.GetTerminal(), ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
code.int3();
diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp
index 6f6d2d7b68..8c55588a28 100644
--- a/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp
+++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp
@@ -48,7 +48,7 @@ bool IsConditionPassed(TranslatorVisitor& v, IR::Cond cond) {
} else {
if (cond == v.ir.block.GetCondition()) {
v.ir.block.SetConditionFailedLocation(v.ir.current_location.AdvancePC(static_cast<int>(v.current_instruction_size)).AdvanceIT());
- v.ir.block.cond_failed_cycle_count++;
+ v.ir.block.ConditionFailedCycleCount()++;
return true;
}
@@ -79,7 +79,7 @@ bool IsConditionPassed(TranslatorVisitor& v, IR::Cond cond) {
v.cond_state = ConditionalState::Translating;
v.ir.block.SetCondition(cond);
v.ir.block.SetConditionFailedLocation(v.ir.current_location.AdvancePC(static_cast<int>(v.current_instruction_size)).AdvanceIT());
- v.ir.block.cond_failed_cycle_count = v.ir.block.cycle_count + 1;
+ v.ir.block.ConditionFailedCycleCount() = v.ir.block.CycleCount() + 1;
return true;
}
diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_arm.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_arm.cpp
index 320046ffc1..5cc9ef3893 100644
--- a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_arm.cpp
+++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_arm.cpp
@@ -61,7 +61,7 @@ void TranslateArm(IR::Block& block, LocationDescriptor descriptor, TranslateCall
}
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
- block.cycle_count += ticks_for_instruction;
+ block.CycleCount() += ticks_for_instruction;
} while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir) && !single_step);
if (visitor.cond_state == ConditionalState::Translating || visitor.cond_state == ConditionalState::Trailing || single_step) {
@@ -101,7 +101,7 @@ bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descript
// TODO: Feedback resulting cond status to caller somehow.
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
- block.cycle_count += ticks_for_instruction;
+ block.CycleCount() += ticks_for_instruction;
block.SetEndLocation(visitor.ir.current_location);
diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp
index a043c3f543..e0333e487d 100644
--- a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp
+++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp
@@ -161,7 +161,7 @@ void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, TranslateCa
}
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(static_cast<int>(visitor.current_instruction_size)).AdvanceIT();
- block.cycle_count += ticks_for_instruction;
+ block.CycleCount() += ticks_for_instruction;
} while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir) && !single_step);
if (visitor.cond_state == ConditionalState::Translating || visitor.cond_state == ConditionalState::Trailing || single_step) {
@@ -214,7 +214,7 @@ bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descri
const s32 advance_pc = is_thumb_16 ? 2 : 4;
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(advance_pc);
- block.cycle_count += ticks_for_instruction;
+ block.CycleCount() += ticks_for_instruction;
block.SetEndLocation(visitor.ir.current_location);
diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
index fc6841e082..6778d13890 100644
--- a/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
+++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
@@ -30,7 +30,7 @@ void Translate(IR::Block& block, LocationDescriptor descriptor, MemoryReadCodeFu
should_continue = visitor.RaiseException(Exception::NoExecuteFault);
}
visitor.ir.current_location = visitor.ir.current_location->AdvancePC(4);
- block.cycle_count++;
+ block.CycleCount()++;
} while (should_continue && !single_step);
if (single_step && should_continue) {
@@ -48,7 +48,7 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
should_continue = decoder.get().call(visitor, instruction);
visitor.ir.current_location = visitor.ir.current_location->AdvancePC(4);
- block.cycle_count++;
+ block.CycleCount()++;
block.SetEndLocation(*visitor.ir.current_location);
diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/system.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/system.cpp
index 61d5c065f4..c60fdc3ae0 100644
--- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/system.cpp
+++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/system.cpp
@@ -130,7 +130,7 @@ bool TranslatorVisitor::MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3
case SystemRegisterEncoding::CNTPCT_EL0:
// HACK: Ensure that this is the first instruction in the block it's emitted in, so the cycle count is most up-to-date.
if (!ir.block.instructions.empty() && !options.wall_clock_cntpct) {
- ir.block.cycle_count--;
+ ir.block.CycleCount()--;
ir.SetTerm(IR::Term::LinkBlock{*ir.current_location});
return false;
}
diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.cpp b/src/dynarmic/src/dynarmic/ir/basic_block.cpp
index 8417661c42..ac0f03d76a 100644
--- a/src/dynarmic/src/dynarmic/ir/basic_block.cpp
+++ b/src/dynarmic/src/dynarmic/ir/basic_block.cpp
@@ -30,26 +30,38 @@ Block::Block(LocationDescriptor location) noexcept
/// Prepends a new instruction to this basic block before the insertion point,
/// handling any allocations necessary to do so.
/// @param insertion_point Where to insert the new instruction.
-/// @param op Opcode representing the instruction to add.
-/// @param args A sequence of Value instances used as arguments for the instruction.
+/// @param op Opcode representing the instruction to add.
+/// @param args A sequence of Value instances used as arguments for the instruction.
/// @returns Iterator to the newly created instruction.
-Block::iterator Block::PrependNewInst(Block::const_iterator insertion_point, Opcode opcode, std::initializer_list<Value> args) noexcept {
+Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, std::initializer_list<Value> args) noexcept {
// First try using the "inline" buffer, otherwise fallback to a slower slab-like allocation scheme
// purpouse is to avoid many calls to new/delete which invoke malloc which invokes mmap
// just pool it!!! - reason why there is an inline buffer is because many small blocks are created
// with few instructions due to subpar optimisations on other passes... plus branch-heavy code will
// hugely benefit from the coherency of faster allocations...
- auto it = instructions.insert(insertion_point, Inst(opcode));
- DEBUG_ASSERT(args.size() == it->NumArgs());
- std::for_each(args.begin(), args.end(), [&it, index = size_t(0)](const auto& arg) mutable {
- it->SetArg(index, arg);
+ IR::Inst* inst;
+ if (inlined_inst.size() < inlined_inst.max_size()) {
+ inlined_inst.emplace_back(opcode);
+ inst = &inlined_inst[inlined_inst.size() - 1];
+ } else {
+ if (pooled_inst.empty() || pooled_inst.back().size() == pooled_inst.back().max_size())
+ pooled_inst.emplace_back();
+ pooled_inst.back().emplace_back(opcode);
+ inst = &pooled_inst.back()[pooled_inst.back().size() - 1];
+ }
+ DEBUG_ASSERT(args.size() == inst->NumArgs());
+ std::for_each(args.begin(), args.end(), [&inst, index = size_t(0)](const auto& arg) mutable {
+ inst->SetArg(index, arg);
index++;
});
- return it;
+ return instructions.insert_before(insertion_point, inst);
}
void Block::Reset(LocationDescriptor location_) noexcept {
- instructions.clear();
+ mcl::intrusive_list<IR::Inst> tmp = {};
+ instructions.swap(tmp);
+ inlined_inst.clear();
+ pooled_inst.clear();
cond_failed.reset();
location = location_;
end_location = location_;
@@ -95,7 +107,7 @@ static std::string TerminalToString(const Terminal& terminal_variant) noexcept {
std::string DumpBlock(const IR::Block& block) noexcept {
std::string ret = fmt::format("Block: location={}-{}\n", block.Location(), block.EndLocation())
- + fmt::format("cycles={}", block.cycle_count)
+ + fmt::format("cycles={}", block.CycleCount())
+ fmt::format(", entry_cond={}", A64::CondToString(block.GetCondition()));
if (block.GetCondition() != Cond::AL)
ret += fmt::format(", cond_fail={}", block.ConditionFailedLocation());
diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.h b/src/dynarmic/src/dynarmic/ir/basic_block.h
index db9ac7bd12..4044005bd0 100644
--- a/src/dynarmic/src/dynarmic/ir/basic_block.h
+++ b/src/dynarmic/src/dynarmic/ir/basic_block.h
@@ -16,6 +16,7 @@
#include <boost/container/container_fwd.hpp>
#include <boost/container/static_vector.hpp>
#include <boost/container/stable_vector.hpp>
+#include <mcl/container/intrusive_list.hpp>
#include "dynarmic/common/common_types.h"
#include "dynarmic/ir/location_descriptor.h"
@@ -32,10 +33,10 @@ enum class Opcode;
/// Note that this is a linear IR and not a pure tree-based IR: i.e.: there is an ordering to
/// the microinstructions. This only matters before chaining is done in order to correctly
/// order memory accesses.
-class Block final {
+class alignas(4096) Block final {
public:
//using instruction_list_type = dense_list<Inst>;
- using instruction_list_type = boost::container::stable_vector<Inst>;
+ using instruction_list_type = mcl::intrusive_list<Inst>;
using size_type = instruction_list_type::size_type;
using iterator = instruction_list_type::iterator;
using const_iterator = instruction_list_type::const_iterator;
@@ -49,9 +50,25 @@ public:
Block(Block&&) = default;
Block& operator=(Block&&) = default;
- iterator PrependNewInst(const_iterator insertion_point, Opcode op, std::initializer_list<Value> args) noexcept;
+ /// Appends a new instruction to the end of this basic block,
+ /// handling any allocations necessary to do so.
+ /// @param op Opcode representing the instruction to add.
+ /// @param args A sequence of Value instances used as arguments for the instruction.
+ inline iterator AppendNewInst(const Opcode opcode, const std::initializer_list<IR::Value> args) noexcept {
+ return PrependNewInst(instructions.end(), opcode, args);
+ }
+ iterator PrependNewInst(iterator insertion_point, Opcode op, std::initializer_list<Value> args) noexcept;
void Reset(LocationDescriptor location_) noexcept;
+ /// Gets a mutable reference to the instruction list for this basic block.
+ inline instruction_list_type& Instructions() noexcept {
+ return instructions;
+ }
+ /// Gets an immutable reference to the instruction list for this basic block.
+ inline const instruction_list_type& Instructions() const noexcept {
+ return instructions;
+ }
+
/// Gets the starting location for this basic block.
inline LocationDescriptor Location() const noexcept {
return location;
@@ -87,6 +104,15 @@ public:
return cond_failed.has_value();
}
+ /// Gets a mutable reference to the condition failed cycle count.
+ inline size_t& ConditionFailedCycleCount() noexcept {
+ return cond_failed_cycle_count;
+ }
+ /// Gets an immutable reference to the condition failed cycle count.
+ inline const size_t& ConditionFailedCycleCount() const noexcept {
+ return cond_failed_cycle_count;
+ }
+
/// Gets the terminal instruction for this basic block.
inline Terminal GetTerminal() const noexcept {
return terminal;
@@ -106,8 +132,21 @@ public:
return terminal.which() != 0;
}
+ /// Gets a mutable reference to the cycle count for this basic block.
+ inline size_t& CycleCount() noexcept {
+ return cycle_count;
+ }
+ /// Gets an immutable reference to the cycle count for this basic block.
+ inline const size_t& CycleCount() const noexcept {
+ return cycle_count;
+ }
+
+ /// "Hot cache" for small blocks so we don't call global allocator
+ boost::container::static_vector<Inst, 30> inlined_inst;
/// List of instructions in this block.
instruction_list_type instructions;
+ /// "Long/far" memory pool
+ boost::container::stable_vector<boost::container::static_vector<Inst, 32>> pooled_inst;
/// Block to execute next if `cond` did not pass.
std::optional<LocationDescriptor> cond_failed = {};
/// Description of the starting location of this block
@@ -123,7 +162,7 @@ public:
/// Number of cycles this block takes to execute.
size_t cycle_count = 0;
};
-//static_assert(sizeof(Block) == 120);
+static_assert(sizeof(Block) == 4096);
/// Returns a string representation of the contents of block. Intended for debugging.
std::string DumpBlock(const IR::Block& block) noexcept;
diff --git a/src/dynarmic/src/dynarmic/ir/ir_emitter.h b/src/dynarmic/src/dynarmic/ir/ir_emitter.h
index becbbf92c7..2b5c7d5cdd 100644
--- a/src/dynarmic/src/dynarmic/ir/ir_emitter.h
+++ b/src/dynarmic/src/dynarmic/ir/ir_emitter.h
@@ -70,10 +70,7 @@ enum class MemOp {
/// The user of this class updates `current_location` as appropriate.
class IREmitter {
public:
- explicit IREmitter(Block& block) noexcept
- : block(block)
- , insertion_point(block.instructions.end())
- {}
+ explicit IREmitter(Block& block) : block(block), insertion_point(block.instructions.end()) {}
Block& block;
@@ -2950,10 +2947,19 @@ public:
block.SetTerminal(terminal);
}
+ void SetInsertionPointBefore(IR::Inst* new_insertion_point) {
+ insertion_point = IR::Block::iterator{*new_insertion_point};
+ }
+
void SetInsertionPointBefore(IR::Block::iterator new_insertion_point) {
insertion_point = new_insertion_point;
}
+ void SetInsertionPointAfter(IR::Inst* new_insertion_point) {
+ insertion_point = IR::Block::iterator{*new_insertion_point};
+ ++insertion_point;
+ }
+
void SetInsertionPointAfter(IR::Block::iterator new_insertion_point) {
insertion_point = new_insertion_point;
++insertion_point;
@@ -2964,10 +2970,7 @@ protected:
template<typename T = Value, typename... Args>
T Inst(Opcode op, Args... args) {
- auto const offset = std::distance(block.instructions.begin(), insertion_point);
- auto const at_end = block.instructions.end() == insertion_point;
auto iter = block.PrependNewInst(insertion_point, op, {Value(args)...});
- insertion_point = at_end ? block.instructions.end() : block.instructions.begin() + (offset + 1);
return T(Value(&*iter));
}
};
diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h
index d1fea62e04..843b4cdf18 100644
--- a/src/dynarmic/src/dynarmic/ir/microinstruction.h
+++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
@@ -10,7 +10,9 @@
#include <array>
+#include <mcl/container/intrusive_list.hpp>
#include "dynarmic/common/common_types.h"
+
#include "dynarmic/ir/value.h"
#include "dynarmic/ir/opcodes.h"
@@ -24,7 +26,7 @@ constexpr size_t max_arg_count = 4;
/// A representation of a microinstruction. A single ARM/Thumb instruction may be
/// converted into zero or more microinstructions.
//class Inst final {
-class Inst final {
+class Inst final : public mcl::intrusive_list_node<Inst> {
public:
explicit Inst(Opcode op) : op(op) {}
diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp
index 1a6670fcca..f22e8aaa69 100644
--- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp
+++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp
@@ -86,10 +86,12 @@ static void ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) {
}
static void FlagsPass(IR::Block& block) {
+ using Iterator = typename std::reverse_iterator<IR::Block::iterator>;
+
struct FlagInfo {
bool set_not_required = false;
bool has_value_request = false;
- IR::Block::reverse_iterator value_request = {};
+ Iterator value_request = {};
};
struct ValuelessFlagInfo {
bool set_not_required = false;
@@ -100,7 +102,7 @@ static void FlagsPass(IR::Block& block) {
FlagInfo c_flag;
FlagInfo ge;
- auto do_set = [&](FlagInfo& info, IR::Value value, IR::Block::reverse_iterator inst) {
+ auto do_set = [&](FlagInfo& info, IR::Value value, Iterator inst) {
if (info.has_value_request) {
info.value_request->ReplaceUsesWith(value);
}
@@ -112,14 +114,14 @@ static void FlagsPass(IR::Block& block) {
info.set_not_required = true;
};
- auto do_set_valueless = [](ValuelessFlagInfo& info, IR::Block::reverse_iterator inst) {
+ auto do_set_valueless = [&](ValuelessFlagInfo& info, Iterator inst) {
if (info.set_not_required) {
inst->Invalidate();
}
info.set_not_required = true;
};
- auto do_get = [](FlagInfo& info, IR::Block::reverse_iterator inst) {
+ auto do_get = [](FlagInfo& info, Iterator inst) {
if (info.has_value_request) {
info.value_request->ReplaceUsesWith(IR::Value{&*inst});
}
@@ -446,8 +448,7 @@ static void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf)
return;
}
- for (auto it = block.instructions.begin(); it != block.instructions.end(); it++) {
- auto& inst = *it;
+ for (auto& inst : block.instructions) {
if (inst.GetOpcode() != IR::Opcode::A64DataCacheOperationRaised) {
continue;
}
@@ -456,7 +457,7 @@ static void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf)
if (op == A64::DataCacheOperation::ZeroByVA) {
A64::IREmitter ir{block};
ir.current_location = A64::LocationDescriptor{IR::LocationDescriptor{inst.GetArg(0).GetU64()}};
- ir.SetInsertionPointBefore(it);
+ ir.SetInsertionPointBefore(&inst);
size_t bytes = 4 << static_cast<size_t>(conf.dczid_el0 & 0b1111);
IR::U64 addr{inst.GetArg(2)};
@@ -521,7 +522,7 @@ static void A64GetSetElimination(IR::Block& block) {
const auto do_set = [&block](RegisterInfo& info, IR::Value value, Iterator set_inst, TrackingType tracking_type) {
if (info.set_instruction_present) {
info.last_set_instruction->Invalidate();
- block.instructions.erase(info.last_set_instruction);
+ block.Instructions().erase(info.last_set_instruction);
}
info.register_value = value;
info.tracking_type = tracking_type;
@@ -540,7 +541,7 @@ static void A64GetSetElimination(IR::Block& block) {
ReplaceUsesWith(*get_inst, true, u32(info.register_value.GetImmediateAsU64()));
} else {
A64::IREmitter ir{block};
- ir.SetInsertionPointBefore(get_inst);
+ ir.SetInsertionPointBefore(&*get_inst);
get_inst->ReplaceUsesWith(ir.LeastSignificantWord(IR::U64{info.register_value}));
}
} else {
@@ -1209,7 +1210,7 @@ static void IdentityRemovalPass(IR::Block& block) {
}
if (it->GetOpcode() == IR::Opcode::Identity || it->GetOpcode() == IR::Opcode::Void) {
to_invalidate.push_back(&*it);
- it = block.instructions.erase(it);
+ it = block.Instructions().erase(it);
} else {
++it;
}
@@ -1369,9 +1370,9 @@ static void PolyfillPass(IR::Block& block, const PolyfillOptions& polyfill) {
IR::IREmitter ir{block};
- for (auto it = block.instructions.begin(); it != block.instructions.end(); it++) {
- auto& inst = *it;
- ir.SetInsertionPointBefore(it);
+ for (auto& inst : block.instructions) {
+ ir.SetInsertionPointBefore(&inst);
+
switch (inst.GetOpcode()) {
case IR::Opcode::SHA256MessageSchedule0:
if (polyfill.sha256) {