mirror of https://github.com/inolen/redream.git
remove blocks from IRBuilder
This commit is contained in:
parent
c44133d574
commit
5a8b1bd530
|
@ -34,10 +34,8 @@ bool InterpreterEmitter::Emit(ir::IRBuilder &builder, void *guest_ctx,
|
|||
// do an initial pass assigning ordinals to instructions so local branches
|
||||
// can be resolved
|
||||
int32_t ordinal = 0;
|
||||
for (auto ir_block : builder.blocks()) {
|
||||
for (auto ir_instr : ir_block->instrs()) {
|
||||
ir_instr->set_tag((intptr_t)ordinal++);
|
||||
}
|
||||
for (auto ir_instr : builder.instrs()) {
|
||||
ir_instr->set_tag((intptr_t)ordinal++);
|
||||
}
|
||||
|
||||
// assign local offsets
|
||||
|
@ -51,15 +49,13 @@ bool InterpreterEmitter::Emit(ir::IRBuilder &builder, void *guest_ctx,
|
|||
// translate each instruction
|
||||
*instr = reinterpret_cast<IntInstr *>(codegen_);
|
||||
|
||||
for (auto ir_block : builder.blocks()) {
|
||||
for (auto ir_instr : ir_block->instrs()) {
|
||||
IntInstr *instr = AllocInstr();
|
||||
if (!instr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TranslateInstr(*ir_instr, instr);
|
||||
for (auto ir_instr : builder.instrs()) {
|
||||
IntInstr *instr = AllocInstr();
|
||||
if (!instr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TranslateInstr(*ir_instr, instr);
|
||||
}
|
||||
|
||||
IntInstr *instr_end = reinterpret_cast<IntInstr *>(codegen_);
|
||||
|
|
|
@ -136,20 +136,18 @@ void X64Emitter::EmitProlog(IRBuilder &builder, int *out_stack_size) {
|
|||
// mark which registers have been modified
|
||||
modified_marker_++;
|
||||
|
||||
for (auto block : builder.blocks()) {
|
||||
for (auto instr : block->instrs()) {
|
||||
Value *result = instr->result();
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int i = result->reg();
|
||||
if (i == NO_REGISTER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
modified_[i] = modified_marker_;
|
||||
for (auto instr : builder.instrs()) {
|
||||
Value *result = instr->result();
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int i = result->reg();
|
||||
if (i == NO_REGISTER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
modified_[i] = modified_marker_;
|
||||
}
|
||||
|
||||
// push the callee-saved registers which have been modified
|
||||
|
@ -182,16 +180,14 @@ void X64Emitter::EmitProlog(IRBuilder &builder, int *out_stack_size) {
|
|||
}
|
||||
|
||||
void X64Emitter::EmitBody(IRBuilder &builder) {
|
||||
for (auto block : builder.blocks()) {
|
||||
for (auto instr : block->instrs()) {
|
||||
X64Emit emit = x64_emitters[instr->op()];
|
||||
CHECK(emit, "Failed to find emitter for %s", Opnames[instr->op()]);
|
||||
for (auto instr : builder.instrs()) {
|
||||
X64Emit emit = x64_emitters[instr->op()];
|
||||
CHECK(emit, "Failed to find emitter for %s", Opnames[instr->op()]);
|
||||
|
||||
// reset temp count used by GetRegister
|
||||
num_temps_ = 0;
|
||||
// reset temp count used by GetRegister
|
||||
num_temps_ = 0;
|
||||
|
||||
emit(*this, instr);
|
||||
}
|
||||
emit(*this, instr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,8 +82,7 @@ void SH4Builder::Emit(uint32_t start_addr, int max_instrs) {
|
|||
}
|
||||
}
|
||||
|
||||
ir::Block *tail_block = blocks_.tail();
|
||||
ir::Instr *tail_instr = tail_block->instrs().tail();
|
||||
ir::Instr *tail_instr = instrs_.tail();
|
||||
|
||||
// if the block was terminated before a branch instruction, emit a
|
||||
// fallthrough branch to the next pc
|
||||
|
@ -93,7 +92,6 @@ void SH4Builder::Emit(uint32_t start_addr, int max_instrs) {
|
|||
}
|
||||
|
||||
// emit block epilog
|
||||
current_block_ = tail_block;
|
||||
current_instr_ = tail_instr->prev();
|
||||
|
||||
Value *remaining_cycles =
|
||||
|
|
|
@ -66,61 +66,14 @@ Local::Local(ValueType ty, Value *offset) : type_(ty), offset_(offset) {}
|
|||
//
|
||||
// Instr
|
||||
//
|
||||
Instr::Instr(Op op)
|
||||
: block_(nullptr),
|
||||
op_(op),
|
||||
args_{{this}, {this}, {this}, {this}},
|
||||
tag_(0) {}
|
||||
Instr::Instr(Op op) : op_(op), args_{{this}, {this}, {this}, {this}}, tag_(0) {}
|
||||
|
||||
Instr::~Instr() {}
|
||||
|
||||
//
|
||||
// Block
|
||||
//
|
||||
Block::Block() : tag_(0) {}
|
||||
Block::~Block() {
|
||||
while (instrs_.tail()) {
|
||||
RemoveInstr(instrs_.tail());
|
||||
}
|
||||
}
|
||||
|
||||
void Block::InsertInstr(Instr *after, Instr *instr) {
|
||||
instr->set_block(this);
|
||||
instrs_.Insert(after, instr);
|
||||
}
|
||||
|
||||
void Block::ReplaceInstr(Instr *replace, Instr *with) {
|
||||
// insert the new instruction
|
||||
InsertInstr(replace, with);
|
||||
|
||||
// replace references to our result with other result
|
||||
if (replace->result()) {
|
||||
CHECK_NOTNULL(with->result());
|
||||
replace->result()->ReplaceRefsWith(with->result());
|
||||
}
|
||||
|
||||
// remove old instruction
|
||||
RemoveInstr(replace);
|
||||
}
|
||||
|
||||
void Block::RemoveInstr(Instr *instr) {
|
||||
instr->set_block(nullptr);
|
||||
instrs_.Remove(instr);
|
||||
|
||||
// call destructor manually
|
||||
instr->~Instr();
|
||||
}
|
||||
|
||||
void Block::UnlinkInstr(Instr *instr) {
|
||||
instr->set_block(nullptr);
|
||||
instrs_.Remove(instr);
|
||||
}
|
||||
|
||||
//
|
||||
// IRBuilder
|
||||
//
|
||||
IRBuilder::IRBuilder()
|
||||
: arena_(1024), current_block_(nullptr), current_instr_(nullptr) {}
|
||||
IRBuilder::IRBuilder() : arena_(1024), current_instr_(nullptr) {}
|
||||
|
||||
void IRBuilder::Dump() const {
|
||||
IRWriter writer;
|
||||
|
@ -129,41 +82,17 @@ void IRBuilder::Dump() const {
|
|||
LOG_INFO(ss.str().c_str());
|
||||
}
|
||||
|
||||
InsertPoint IRBuilder::GetInsertPoint() {
|
||||
return {current_block_, current_instr_};
|
||||
}
|
||||
InsertPoint IRBuilder::GetInsertPoint() { return {current_instr_}; }
|
||||
|
||||
void IRBuilder::SetInsertPoint(const InsertPoint &point) {
|
||||
current_block_ = point.block;
|
||||
current_instr_ = point.instr;
|
||||
}
|
||||
|
||||
Block *IRBuilder::InsertBlock(Block *after) {
|
||||
Block *block = arena_.Alloc<Block>();
|
||||
new (block) Block();
|
||||
void IRBuilder::RemoveInstr(Instr *instr) {
|
||||
instrs_.Remove(instr);
|
||||
|
||||
// insert at beginning if no after specified
|
||||
if (!after) {
|
||||
blocks_.Insert(nullptr, block);
|
||||
} else {
|
||||
blocks_.Insert(after, block);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
Block *IRBuilder::AppendBlock() { return InsertBlock(blocks_.tail()); }
|
||||
|
||||
void IRBuilder::RemoveBlock(Block *block) {
|
||||
if (current_block_ == block) {
|
||||
current_block_ = block->next() ? block->next() : block->prev();
|
||||
current_instr_ = current_block_->instrs().tail();
|
||||
}
|
||||
|
||||
blocks_.Remove(block);
|
||||
|
||||
// call destructor manually
|
||||
block->~Block();
|
||||
// call destructor manually to release value references
|
||||
instr->~Instr();
|
||||
}
|
||||
|
||||
Value *IRBuilder::LoadHost(Value *addr, ValueType type) {
|
||||
|
@ -678,13 +607,8 @@ Instr *IRBuilder::AllocInstr(Op op) {
|
|||
}
|
||||
|
||||
Instr *IRBuilder::AppendInstr(Op op) {
|
||||
if (!current_block_) {
|
||||
current_block_ = InsertBlock(current_block_);
|
||||
current_instr_ = nullptr;
|
||||
}
|
||||
|
||||
Instr *instr = AllocInstr(op);
|
||||
current_block_->InsertInstr(current_instr_, instr);
|
||||
instrs_.Insert(current_instr_, instr);
|
||||
current_instr_ = instr;
|
||||
return instr;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ enum {
|
|||
NO_REGISTER = -1,
|
||||
};
|
||||
|
||||
class Block;
|
||||
class Instr;
|
||||
class ValueRef;
|
||||
|
||||
|
@ -254,15 +253,10 @@ class Local : public IntrusiveListNode<Local> {
|
|||
// instructions
|
||||
//
|
||||
class Instr : public IntrusiveListNode<Instr> {
|
||||
friend class Block;
|
||||
|
||||
public:
|
||||
Instr(Op op);
|
||||
~Instr();
|
||||
|
||||
const Block *block() const { return block_; }
|
||||
Block *block() { return block_; }
|
||||
|
||||
Op op() const { return op_; }
|
||||
|
||||
const Value *arg0() const { return arg(0); }
|
||||
|
@ -289,47 +283,17 @@ class Instr : public IntrusiveListNode<Instr> {
|
|||
void set_tag(intptr_t tag) { tag_ = tag; }
|
||||
|
||||
private:
|
||||
Block *set_block(Block *block) { return block_ = block; }
|
||||
|
||||
Block *block_;
|
||||
Op op_;
|
||||
ValueRef args_[4];
|
||||
intptr_t tag_;
|
||||
};
|
||||
|
||||
//
|
||||
// blocks
|
||||
//
|
||||
class Block : public IntrusiveListNode<Block> {
|
||||
friend class IRBuilder;
|
||||
|
||||
public:
|
||||
Block();
|
||||
~Block();
|
||||
|
||||
const IntrusiveList<Instr> &instrs() const { return instrs_; }
|
||||
IntrusiveList<Instr> &instrs() { return instrs_; }
|
||||
|
||||
intptr_t tag() const { return tag_; }
|
||||
void set_tag(intptr_t tag) { tag_ = tag; }
|
||||
|
||||
void InsertInstr(Instr *after, Instr *instr);
|
||||
void ReplaceInstr(Instr *replace, Instr *with);
|
||||
void RemoveInstr(Instr *instr);
|
||||
void UnlinkInstr(Instr *instr);
|
||||
|
||||
private:
|
||||
IntrusiveList<Instr> instrs_;
|
||||
intptr_t tag_;
|
||||
};
|
||||
|
||||
//
|
||||
// IRBuilder
|
||||
//
|
||||
typedef void (*ExternalFn)(void *);
|
||||
|
||||
struct InsertPoint {
|
||||
Block *block;
|
||||
Instr *instr;
|
||||
};
|
||||
|
||||
|
@ -339,8 +303,8 @@ class IRBuilder {
|
|||
public:
|
||||
IRBuilder();
|
||||
|
||||
const IntrusiveList<Block> &blocks() const { return blocks_; }
|
||||
IntrusiveList<Block> &blocks() { return blocks_; }
|
||||
const IntrusiveList<Instr> &instrs() const { return instrs_; }
|
||||
IntrusiveList<Instr> &instrs() { return instrs_; }
|
||||
|
||||
const IntrusiveList<Local> &locals() const { return locals_; }
|
||||
IntrusiveList<Local> &locals() { return locals_; }
|
||||
|
@ -350,10 +314,7 @@ class IRBuilder {
|
|||
InsertPoint GetInsertPoint();
|
||||
void SetInsertPoint(const InsertPoint &point);
|
||||
|
||||
// blocks
|
||||
Block *InsertBlock(Block *after);
|
||||
Block *AppendBlock();
|
||||
void RemoveBlock(Block *block);
|
||||
void RemoveInstr(Instr *instr);
|
||||
|
||||
// direct access to host memory
|
||||
Value *LoadHost(Value *addr, ValueType type);
|
||||
|
@ -437,9 +398,8 @@ class IRBuilder {
|
|||
Instr *AppendInstr(Op op);
|
||||
|
||||
Arena arena_;
|
||||
IntrusiveList<Block> blocks_;
|
||||
IntrusiveList<Instr> instrs_;
|
||||
IntrusiveList<Local> locals_;
|
||||
Block *current_block_;
|
||||
Instr *current_instr_;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,10 +8,8 @@ void IRWriter::Print(const IRBuilder &builder, std::ostream &output) {
|
|||
slots_.clear();
|
||||
next_slot_ = 0;
|
||||
|
||||
for (auto block : builder.blocks()) {
|
||||
for (auto instr : block->instrs()) {
|
||||
PrintInstruction(instr, output);
|
||||
}
|
||||
for (auto instr : builder.instrs()) {
|
||||
PrintInstruction(instr, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
using namespace re::jit::ir;
|
||||
using namespace re::jit::ir::passes;
|
||||
|
||||
typedef void (*FoldFn)(IRBuilder &, Block *, Instr *i);
|
||||
typedef void (*FoldFn)(IRBuilder &, Instr *i);
|
||||
|
||||
// specify which arguments must be constant in order for fold operation to run
|
||||
enum {
|
||||
|
@ -35,7 +35,7 @@ int fold_masks[NUM_OPS];
|
|||
} op##_init; \
|
||||
template <typename R = ValueInfo<VALUE_V>, typename A0 = ValueInfo<VALUE_V>, \
|
||||
typename A1 = ValueInfo<VALUE_V>> \
|
||||
void Handle##op(IRBuilder &builder, Block *block, Instr *instr)
|
||||
void Handle##op(IRBuilder &builder, Instr *instr)
|
||||
|
||||
// registers a fold callback for the specified signature
|
||||
#define REGISTER_FOLD(op, r, a0, a1) \
|
||||
|
@ -57,7 +57,7 @@ int fold_masks[NUM_OPS];
|
|||
#define RESULT(expr) \
|
||||
instr->result()->ReplaceRefsWith( \
|
||||
builder.AllocConstant(static_cast<typename R::signed_type>(expr))); \
|
||||
block->RemoveInstr(instr)
|
||||
builder.RemoveInstr(instr)
|
||||
|
||||
static FoldFn GetFoldFn(Instr *instr) {
|
||||
auto it = fold_cbs.find(CALLBACK_IDX(
|
||||
|
@ -93,32 +93,30 @@ static int GetConstantSig(Instr *instr) {
|
|||
void ConstantPropagationPass::Run(IRBuilder &builder) {
|
||||
PROFILER_RUNTIME("ConstantPropagationPass::Run");
|
||||
|
||||
for (auto block : builder.blocks()) {
|
||||
auto it = block->instrs().begin();
|
||||
auto end = block->instrs().end();
|
||||
auto it = builder.instrs().begin();
|
||||
auto end = builder.instrs().end();
|
||||
|
||||
while (it != end) {
|
||||
Instr *instr = *(it++);
|
||||
while (it != end) {
|
||||
Instr *instr = *(it++);
|
||||
|
||||
int fold_mask = GetFoldMask(instr);
|
||||
int cnst_sig = GetConstantSig(instr);
|
||||
if (!fold_mask || (cnst_sig & fold_mask) != fold_mask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FoldFn fold = GetFoldFn(instr);
|
||||
if (!fold) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fold(builder, block, instr);
|
||||
int fold_mask = GetFoldMask(instr);
|
||||
int cnst_sig = GetConstantSig(instr);
|
||||
if (!fold_mask || (cnst_sig & fold_mask) != fold_mask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FoldFn fold = GetFoldFn(instr);
|
||||
if (!fold) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fold(builder, instr);
|
||||
}
|
||||
}
|
||||
|
||||
FOLD(SELECT, ARG0_CNST) {
|
||||
instr->result()->ReplaceRefsWith(ARG0() ? instr->arg1() : instr->arg2());
|
||||
block->RemoveInstr(instr);
|
||||
builder.RemoveInstr(instr);
|
||||
}
|
||||
REGISTER_FOLD(SELECT, I8, I8, I8);
|
||||
REGISTER_FOLD(SELECT, I16, I16, I16);
|
||||
|
|
|
@ -12,18 +12,10 @@ void LoadStoreEliminationPass::Run(IRBuilder &builder) {
|
|||
|
||||
Reset();
|
||||
|
||||
for (auto block : builder.blocks()) {
|
||||
ProcessBlock(block);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadStoreEliminationPass::Reset() { ClearAvailable(); }
|
||||
|
||||
void LoadStoreEliminationPass::ProcessBlock(Block *block) {
|
||||
// eliminate redundant loads
|
||||
{
|
||||
auto it = block->instrs().begin();
|
||||
auto end = block->instrs().end();
|
||||
auto it = builder.instrs().begin();
|
||||
auto end = builder.instrs().end();
|
||||
|
||||
ClearAvailable();
|
||||
|
||||
|
@ -39,7 +31,7 @@ void LoadStoreEliminationPass::ProcessBlock(Block *block) {
|
|||
if (available && available->type() == instr->result()->type()) {
|
||||
instr->result()->ReplaceRefsWith(available);
|
||||
CHECK_EQ(instr->result(), available);
|
||||
block->RemoveInstr(instr);
|
||||
builder.RemoveInstr(instr);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -56,8 +48,8 @@ void LoadStoreEliminationPass::ProcessBlock(Block *block) {
|
|||
// eliminate dead stores
|
||||
{
|
||||
// iterate in reverse so the current instruction is the one being removed
|
||||
auto it = block->instrs().rbegin();
|
||||
auto end = block->instrs().rend();
|
||||
auto it = builder.instrs().rbegin();
|
||||
auto end = builder.instrs().rend();
|
||||
|
||||
ClearAvailable();
|
||||
|
||||
|
@ -78,7 +70,7 @@ void LoadStoreEliminationPass::ProcessBlock(Block *block) {
|
|||
int store_size = SizeForType(instr->arg1()->type());
|
||||
|
||||
if (available_size >= store_size) {
|
||||
block->RemoveInstr(instr);
|
||||
builder.RemoveInstr(instr);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -88,6 +80,8 @@ void LoadStoreEliminationPass::ProcessBlock(Block *block) {
|
|||
}
|
||||
}
|
||||
|
||||
void LoadStoreEliminationPass::Reset() { ClearAvailable(); }
|
||||
|
||||
void LoadStoreEliminationPass::Reserve(int offset) {
|
||||
int reserve = offset + 1;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ class LoadStoreEliminationPass : public Pass {
|
|||
|
||||
private:
|
||||
void Reset();
|
||||
void ProcessBlock(Block *block);
|
||||
|
||||
void Reserve(int offset);
|
||||
void ClearAvailable();
|
||||
|
|
|
@ -93,47 +93,45 @@ RegisterAllocationPass::~RegisterAllocationPass() { delete[] intervals_; }
|
|||
void RegisterAllocationPass::Run(IRBuilder &builder) {
|
||||
PROFILER_RUNTIME("RegisterAllocationPass::Run");
|
||||
|
||||
for (auto block : builder.blocks()) {
|
||||
Reset();
|
||||
Reset();
|
||||
|
||||
AssignOrdinals(block);
|
||||
AssignOrdinals(builder);
|
||||
|
||||
for (auto instr : block->instrs()) {
|
||||
Value *result = instr->result();
|
||||
for (auto instr : builder.instrs()) {
|
||||
Value *result = instr->result();
|
||||
|
||||
// only allocate registers for results, assume constants can always be
|
||||
// encoded as immediates or that the backend has registers reserved
|
||||
// for storing the constants
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// sort the value's ref list
|
||||
result->refs().Sort([](const ValueRef *a, const ValueRef *b) {
|
||||
return GetOrdinal(a->instr()) < GetOrdinal(b->instr());
|
||||
});
|
||||
|
||||
// get the live range of the value
|
||||
ValueRef *start = result->refs().head();
|
||||
ValueRef *end = result->refs().tail();
|
||||
|
||||
// expire any old intervals, freeing up the registers they claimed
|
||||
ExpireOldIntervals(start->instr());
|
||||
|
||||
// first, try and reuse the register of one of the incoming arguments
|
||||
int reg = ReuuseArgRegister(instr, start, end);
|
||||
if (reg == NO_REGISTER) {
|
||||
// else, allocate a new register for the result
|
||||
reg = AllocFreeRegister(result, start, end);
|
||||
if (reg == NO_REGISTER) {
|
||||
// if a register couldn't be allocated, spill a register and try again
|
||||
reg = AllocBlockedRegister(builder, result, start, end);
|
||||
CHECK_NE(reg, NO_REGISTER, "Failed to allocate register");
|
||||
}
|
||||
}
|
||||
|
||||
result->set_reg(reg);
|
||||
// only allocate registers for results, assume constants can always be
|
||||
// encoded as immediates or that the backend has registers reserved
|
||||
// for storing the constants
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// sort the value's ref list
|
||||
result->refs().Sort([](const ValueRef *a, const ValueRef *b) {
|
||||
return GetOrdinal(a->instr()) < GetOrdinal(b->instr());
|
||||
});
|
||||
|
||||
// get the live range of the value
|
||||
ValueRef *start = result->refs().head();
|
||||
ValueRef *end = result->refs().tail();
|
||||
|
||||
// expire any old intervals, freeing up the registers they claimed
|
||||
ExpireOldIntervals(start->instr());
|
||||
|
||||
// first, try and reuse the register of one of the incoming arguments
|
||||
int reg = ReuuseArgRegister(instr, start, end);
|
||||
if (reg == NO_REGISTER) {
|
||||
// else, allocate a new register for the result
|
||||
reg = AllocFreeRegister(result, start, end);
|
||||
if (reg == NO_REGISTER) {
|
||||
// if a register couldn't be allocated, spill a register and try again
|
||||
reg = AllocBlockedRegister(builder, result, start, end);
|
||||
CHECK_NE(reg, NO_REGISTER, "Failed to allocate register");
|
||||
}
|
||||
}
|
||||
|
||||
result->set_reg(reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,11 +166,11 @@ void RegisterAllocationPass::Reset() {
|
|||
}
|
||||
}
|
||||
|
||||
void RegisterAllocationPass::AssignOrdinals(Block *block) {
|
||||
void RegisterAllocationPass::AssignOrdinals(IRBuilder &builder) {
|
||||
// assign each instruction an ordinal. these ordinals are used to describe
|
||||
// the live range of a particular value
|
||||
int ordinal = 0;
|
||||
for (auto instr : block->instrs()) {
|
||||
for (auto instr : builder.instrs()) {
|
||||
SetOrdinal(instr, ordinal);
|
||||
|
||||
// space out ordinals to leave available values for instructions inserted
|
||||
|
@ -308,7 +306,7 @@ int RegisterAllocationPass::AllocBlockedRegister(IRBuilder &builder,
|
|||
Local *local = builder.AllocLocal(interval->value->type());
|
||||
|
||||
// insert load before next use
|
||||
builder.SetInsertPoint({insert_point.block, next_ref->instr()->prev()});
|
||||
builder.SetInsertPoint({next_ref->instr()->prev()});
|
||||
Value *load_local = builder.LoadLocal(local);
|
||||
Instr *load_instr = builder.GetInsertPoint().instr;
|
||||
|
||||
|
@ -337,7 +335,7 @@ int RegisterAllocationPass::AllocBlockedRegister(IRBuilder &builder,
|
|||
// instruction is created and added as a reference, the sorted order will be
|
||||
// invalidated. because of this, the save instruction needs to be added after
|
||||
// the load instruction has updated the sorted references.
|
||||
builder.SetInsertPoint({insert_point.block, prev_ref->instr()});
|
||||
builder.SetInsertPoint({prev_ref->instr()});
|
||||
builder.StoreLocal(local, interval->value);
|
||||
Instr *store_instr = builder.GetInsertPoint().instr;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ class RegisterAllocationPass : public Pass {
|
|||
RegisterSet &GetRegisterSet(ValueType type);
|
||||
|
||||
void Reset();
|
||||
void AssignOrdinals(ir::Block *block);
|
||||
void AssignOrdinals(IRBuilder &builder);
|
||||
void ExpireOldIntervals(Instr *start);
|
||||
int ReuuseArgRegister(Instr *instr, ValueRef *start, ValueRef *end);
|
||||
int AllocFreeRegister(Value *value, ValueRef *start, ValueRef *end);
|
||||
|
|
|
@ -11,8 +11,6 @@ namespace passes {
|
|||
class ValidatePass : public Pass {
|
||||
public:
|
||||
void Run(IRBuilder &builder);
|
||||
void ValidateBlock(IRBuilder &builder, Block *block);
|
||||
void ValidateInstr(IRBuilder &builder, Block *block, Instr *instr);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ TEST(LoadStoreEliminationPassTest, Aliasing) {
|
|||
"i32 %8 = load_context i32 0x2c\n"
|
||||
"i32 %9 = load_context i32 0x20\n"
|
||||
"i32 %10 = sub i32 %9, i32 0x10\n"
|
||||
"store_context i32 0x20, i32 %10\n"
|
||||
"branch i32 %8\n";
|
||||
"store_context i32 0x20, i32 %10\n";
|
||||
|
||||
static const char *output =
|
||||
"store_context i32 0x104, i32 0x0\n"
|
||||
|
@ -57,8 +56,7 @@ TEST(LoadStoreEliminationPassTest, Aliasing) {
|
|||
"i32 %3 = load_context i32 0x2c\n"
|
||||
"i32 %4 = load_context i32 0x20\n"
|
||||
"i32 %5 = sub i32 %4, i32 0x10\n"
|
||||
"store_context i32 0x20, i32 %5\n"
|
||||
"branch i32 %3\n";
|
||||
"store_context i32 0x20, i32 %5\n";
|
||||
|
||||
IRBuilder builder;
|
||||
|
||||
|
|
Loading…
Reference in New Issue