mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
IR: Keep IRWriter's instructions in a FastVec, and inline Write
The compiler didn't inline std::vector<IRInst>::push_back into IRWriter::Write, which the frontend and every pass call for each instruction. FastVec's append is a compare and a store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
235c5ba87b
commit
dcc51d8b18
4 files changed
+26
-17
No files matched your search
@@ -387,10 +387,10 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, u32 &m
|
||||
}
|
||||
|
||||
if (!mipsTracer.tracing_enabled) {
|
||||
instructions = code->GetInstructions();
|
||||
instructions.assign(code->GetInstructions().begin(), code->GetInstructions().end());
|
||||
}
|
||||
else {
|
||||
std::vector<IRInst> block_instructions = code->GetInstructions();
|
||||
std::vector<IRInst> block_instructions(code->GetInstructions().begin(), code->GetInstructions().end());
|
||||
instructions.reserve(block_instructions.size() + 2); // +2 for Downcount and LogIRBlock
|
||||
// The first instruction is "Downcount"
|
||||
instructions.push_back(block_instructions.front());
|
||||
|
||||
@@ -231,16 +231,6 @@ void InitIR() {
|
||||
}
|
||||
}
|
||||
|
||||
void IRWriter::Write(IROp op, u8 dst, u8 src1, u8 src2, u32 constant) {
|
||||
IRInst inst;
|
||||
inst.op = op;
|
||||
inst.dest = dst;
|
||||
inst.src1 = src1;
|
||||
inst.src2 = src2;
|
||||
inst.constant = constant;
|
||||
insts_.push_back(inst);
|
||||
}
|
||||
|
||||
void IRWriter::WriteFC(IROp op, u8 dst, u8 src1, u8 src2, float fconstant) {
|
||||
u32 constant;
|
||||
memcpy(&constant, &fconstant, sizeof(u32));
|
||||
|
||||
+23
-4
@@ -5,6 +5,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Data/Collections/FastVec.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
|
||||
// Basic IR
|
||||
@@ -424,8 +425,17 @@ u32 IRInterpret(MIPSState *ms, const IRInst *inst, const IRInst *chainArena = nu
|
||||
// Each IR block gets a constant pool.
|
||||
class IRWriter {
|
||||
public:
|
||||
IRWriter() {}
|
||||
IRWriter(const IRWriter &w) {
|
||||
*this = w;
|
||||
}
|
||||
IRWriter(IRWriter &&w) noexcept : insts_(std::move(w.insts_)) {}
|
||||
IRWriter &operator =(const IRWriter &w) {
|
||||
insts_ = w.insts_;
|
||||
if (this != &w) {
|
||||
insts_.clear();
|
||||
if (!w.insts_.empty())
|
||||
insts_.extend(w.insts_.data(), w.insts_.size());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
IRWriter &operator =(IRWriter &&w) noexcept {
|
||||
@@ -433,7 +443,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Write(IROp op, u8 dst = 0, u8 src1 = 0, u8 src2 = 0, u32 constant = 0);
|
||||
// Inline (with FastVec rather than std::vector, which the compiler didn't inline), since the
|
||||
// frontend and every pass write each instruction through these.
|
||||
void Write(IROp op, u8 dst = 0, u8 src1 = 0, u8 src2 = 0, u32 constant = 0) {
|
||||
IRInst &inst = insts_.push_uninitialized();
|
||||
inst.op = op;
|
||||
inst.dest = dst;
|
||||
inst.src1 = src1;
|
||||
inst.src2 = src2;
|
||||
inst.constant = constant;
|
||||
}
|
||||
void WriteFC(IROp op, u8 dst, u8 src1, u8 src2, float fconstant);
|
||||
|
||||
void WriteSetConstant(u8 dst, u32 value);
|
||||
@@ -450,10 +469,10 @@ public:
|
||||
}
|
||||
void ReplaceConstant(size_t instNumber, u32 newConstant);
|
||||
|
||||
const std::vector<IRInst> &GetInstructions() const { return insts_; }
|
||||
const FastVec<IRInst> &GetInstructions() const { return insts_; }
|
||||
|
||||
private:
|
||||
std::vector<IRInst> insts_;
|
||||
FastVec<IRInst> insts_;
|
||||
};
|
||||
|
||||
// How far IRFrontend compiles on past conditional branches. The interpreter ends its blocks in the
|
||||
|
||||
@@ -57,7 +57,7 @@ static bool VerifyPass(const IRVerification &v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<IRInst> actual = out.GetInstructions();
|
||||
const std::vector<IRInst> actual(out.GetInstructions().begin(), out.GetInstructions().end());
|
||||
if (actual.size() != v.expected.size()) {
|
||||
printf("%s FAILED: produced %d instructions, expected %d\n", v.name, (int)actual.size(), (int)v.expected.size());
|
||||
printf("Actual:\n");
|
||||
|
||||
Reference in new issue
Block a user