mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
rose: minor improvements to avoid unneeded program instructions
- strip out lonely check handled instructions - avoid producing programs for empty ghost roles
This commit is contained in:
parent
88fd95e38a
commit
e24c38a85c
@ -4163,8 +4163,9 @@ void makeRoleEagerEodReports(const RoseBuildImpl &build, build_context &bc,
|
|||||||
program.add_before_end(move(eod_program));
|
program.add_before_end(move(eod_program));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Makes a program for a role/vertex given a specfic pred/in_edge. */
|
||||||
static
|
static
|
||||||
RoseProgram makeProgram(const RoseBuildImpl &build, build_context &bc,
|
RoseProgram makeRoleProgram(const RoseBuildImpl &build, build_context &bc,
|
||||||
ProgramBuild &prog_build, const RoseEdge &e) {
|
ProgramBuild &prog_build, const RoseEdge &e) {
|
||||||
const RoseGraph &g = build.g;
|
const RoseGraph &g = build.g;
|
||||||
auto v = target(e, g);
|
auto v = target(e, g);
|
||||||
@ -4187,10 +4188,11 @@ RoseProgram makeProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
makeRoleCheckBounds(build, v, e, program);
|
makeRoleCheckBounds(build, v, e, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This program may be triggered by different predecessors, with different
|
// This role program may be triggered by different predecessors, with
|
||||||
// offset bounds. We must ensure we put this check/set operation after the
|
// different offset bounds. We must ensure we put this check/set operation
|
||||||
// bounds check to deal with this case.
|
// after the bounds check to deal with this case.
|
||||||
if (in_degree(v, g) > 1) {
|
if (in_degree(v, g) > 1) {
|
||||||
|
assert(!build.isRootSuccessor(v));
|
||||||
makeRoleCheckNotHandled(prog_build, v, program);
|
makeRoleCheckNotHandled(prog_build, v, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4231,6 +4233,12 @@ RoseProgram makeProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
makeRoleEagerEodReports(build, bc, v, eod_block);
|
makeRoleEagerEodReports(build, bc, v, eod_block);
|
||||||
effects_block.add_block(move(eod_block));
|
effects_block.add_block(move(eod_block));
|
||||||
|
|
||||||
|
/* a 'ghost role' may do nothing if we know that its groups are already set
|
||||||
|
* - in this case we can avoid producing a program at all. */
|
||||||
|
if (effects_block.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
program.add_before_end(move(effects_block));
|
program.add_before_end(move(effects_block));
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
@ -4414,6 +4422,7 @@ void addPredBlockSingle(u32 pred_state, RoseProgram &pred_block,
|
|||||||
RoseProgram &program) {
|
RoseProgram &program) {
|
||||||
// Prepend an instruction to check the pred state is on.
|
// Prepend an instruction to check the pred state is on.
|
||||||
const auto *end_inst = pred_block.end_instruction();
|
const auto *end_inst = pred_block.end_instruction();
|
||||||
|
assert(!pred_block.empty());
|
||||||
pred_block.insert(begin(pred_block),
|
pred_block.insert(begin(pred_block),
|
||||||
make_unique<RoseInstrCheckState>(pred_state, end_inst));
|
make_unique<RoseInstrCheckState>(pred_state, end_inst));
|
||||||
program.add_block(move(pred_block));
|
program.add_block(move(pred_block));
|
||||||
@ -4434,6 +4443,12 @@ void addPredBlocksAny(map<u32, RoseProgram> &pred_blocks, u32 num_states,
|
|||||||
sparse_program.add_before_end(move(ri));
|
sparse_program.add_before_end(move(ri));
|
||||||
|
|
||||||
RoseProgram &block = pred_blocks.begin()->second;
|
RoseProgram &block = pred_blocks.begin()->second;
|
||||||
|
assert(!block.empty());
|
||||||
|
|
||||||
|
/* we no longer need the check handled instruction as all the pred-role
|
||||||
|
* blocks are being collapsed together */
|
||||||
|
stripCheckHandledInstruction(block);
|
||||||
|
|
||||||
sparse_program.add_before_end(move(block));
|
sparse_program.add_before_end(move(block));
|
||||||
program.add_block(move(sparse_program));
|
program.add_block(move(sparse_program));
|
||||||
}
|
}
|
||||||
@ -4491,15 +4506,6 @@ void addPredBlocksMulti(map<u32, RoseProgram> &pred_blocks,
|
|||||||
static
|
static
|
||||||
void addPredBlocks(map<u32, RoseProgram> &pred_blocks, u32 num_states,
|
void addPredBlocks(map<u32, RoseProgram> &pred_blocks, u32 num_states,
|
||||||
RoseProgram &program) {
|
RoseProgram &program) {
|
||||||
// Trim empty blocks, if any exist.
|
|
||||||
for (auto it = pred_blocks.begin(); it != pred_blocks.end();) {
|
|
||||||
if (it->second.empty()) {
|
|
||||||
it = pred_blocks.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t num_preds = pred_blocks.size();
|
const size_t num_preds = pred_blocks.size();
|
||||||
if (num_preds == 0) {
|
if (num_preds == 0) {
|
||||||
return;
|
return;
|
||||||
@ -4815,8 +4821,10 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
g[target(e, g)].index);
|
g[target(e, g)].index);
|
||||||
assert(contains(bc.roleStateIndices, u));
|
assert(contains(bc.roleStateIndices, u));
|
||||||
u32 pred_state = bc.roleStateIndices.at(u);
|
u32 pred_state = bc.roleStateIndices.at(u);
|
||||||
pred_blocks[pred_state].add_block(
|
auto role_prog = makeRoleProgram(build, bc, prog_build, e);
|
||||||
makeProgram(build, bc, prog_build, e));
|
if (!role_prog.empty()) {
|
||||||
|
pred_blocks[pred_state].add_block(move(role_prog));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add blocks to deal with non-root edges (triggered by sparse iterator or
|
// Add blocks to deal with non-root edges (triggered by sparse iterator or
|
||||||
@ -4831,7 +4839,7 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
}
|
}
|
||||||
DEBUG_PRINTF("root edge (%zu,%zu)\n", g[u].index,
|
DEBUG_PRINTF("root edge (%zu,%zu)\n", g[u].index,
|
||||||
g[target(e, g)].index);
|
g[target(e, g)].index);
|
||||||
program.add_block(makeProgram(build, bc, prog_build, e));
|
program.add_block(makeRoleProgram(build, bc, prog_build, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lit_id == build.eod_event_literal_id) {
|
if (lit_id == build.eod_event_literal_id) {
|
||||||
@ -4872,6 +4880,7 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
if (contains(lit_edge_map, lit_id)) {
|
if (contains(lit_edge_map, lit_id)) {
|
||||||
edges_ptr = &lit_edge_map.at(lit_id);
|
edges_ptr = &lit_edge_map.at(lit_id);
|
||||||
} else {
|
} else {
|
||||||
|
/* literal may happen only in a delay context */
|
||||||
edges_ptr = &no_edges;
|
edges_ptr = &no_edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5205,7 +5214,8 @@ pair<u32, u32> writeAnchoredPrograms(const RoseBuildImpl &build,
|
|||||||
auto it = cache.find(offset);
|
auto it = cache.find(offset);
|
||||||
if (it != end(cache)) {
|
if (it != end(cache)) {
|
||||||
anch_id = it->second;
|
anch_id = it->second;
|
||||||
DEBUG_PRINTF("reusing anch_id %u for offset %u\n", anch_id, offset);
|
DEBUG_PRINTF("reusing anch_id %u for offset %u\n", anch_id,
|
||||||
|
offset);
|
||||||
} else {
|
} else {
|
||||||
anch_id = verify_u32(programs.size());
|
anch_id = verify_u32(programs.size());
|
||||||
programs.push_back(offset);
|
programs.push_back(offset);
|
||||||
|
@ -639,6 +639,11 @@ OffsetMap makeOffsetMap(const RoseProgram &program, u32 *total_len) {
|
|||||||
return offset_map;
|
return offset_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RoseProgram::iterator RoseProgram::erase(RoseProgram::iterator first,
|
||||||
|
RoseProgram::iterator last) {
|
||||||
|
return prog.erase(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
bytecode_ptr<char> writeProgram(RoseEngineBlob &blob,
|
bytecode_ptr<char> writeProgram(RoseEngineBlob &blob,
|
||||||
const RoseProgram &program) {
|
const RoseProgram &program) {
|
||||||
u32 total_len = 0;
|
u32 total_len = 0;
|
||||||
@ -681,6 +686,28 @@ bool RoseProgramEquivalence::operator()(const RoseProgram &prog1,
|
|||||||
return std::equal(prog1.begin(), prog1.end(), prog2.begin(), is_equiv);
|
return std::equal(prog1.begin(), prog1.end(), prog2.begin(), is_equiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stripCheckHandledInstruction(RoseProgram &prog) {
|
||||||
|
for (auto it = prog.begin(); it != prog.end();) {
|
||||||
|
auto ins = dynamic_cast<const RoseInstrCheckNotHandled *>(it->get());
|
||||||
|
if (!ins) {
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto next_it = next(it);
|
||||||
|
assert(next_it != prog.end()); /* there should always be an end ins */
|
||||||
|
auto next_ins = next_it->get();
|
||||||
|
|
||||||
|
/* update all earlier instructions which point to ins to instead point
|
||||||
|
* to the next instruction. Only need to look at earlier as we only ever
|
||||||
|
* jump forward. */
|
||||||
|
RoseProgram::update_targets(prog.begin(), it, ins, next_ins);
|
||||||
|
|
||||||
|
/* remove check handled instruction */
|
||||||
|
it = prog.erase(it, next_it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool reads_work_done_flag(const RoseProgram &prog) {
|
bool reads_work_done_flag(const RoseProgram &prog) {
|
||||||
for (const auto &ri : prog) {
|
for (const auto &ri : prog) {
|
||||||
if (dynamic_cast<const RoseInstrSquashGroups *>(ri.get())) {
|
if (dynamic_cast<const RoseInstrSquashGroups *>(ri.get())) {
|
||||||
|
@ -2219,7 +2219,6 @@ public:
|
|||||||
return prog.back().get();
|
return prog.back().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static void update_targets(iterator it, iterator it_end,
|
static void update_targets(iterator it, iterator it_end,
|
||||||
const RoseInstruction *old_target,
|
const RoseInstruction *old_target,
|
||||||
const RoseInstruction *new_target) {
|
const RoseInstruction *new_target) {
|
||||||
@ -2231,7 +2230,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
iterator insert(iterator it, std::unique_ptr<RoseInstruction> ri) {
|
iterator insert(iterator it, std::unique_ptr<RoseInstruction> ri) {
|
||||||
assert(!prog.empty());
|
assert(!prog.empty());
|
||||||
assert(it != end());
|
assert(it != end());
|
||||||
@ -2267,6 +2265,10 @@ public:
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: takes iterator rather than const_iterator to support toolchains
|
||||||
|
* with pre-C++11 standard libraries (i.e., gcc-4.8). */
|
||||||
|
iterator erase(iterator first, iterator last);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Adds this instruction to the program just before the terminating
|
* \brief Adds this instruction to the program just before the terminating
|
||||||
* ROSE_INSTR_END.
|
* ROSE_INSTR_END.
|
||||||
@ -2348,6 +2350,9 @@ public:
|
|||||||
bool operator()(const RoseProgram &prog1, const RoseProgram &prog2) const;
|
bool operator()(const RoseProgram &prog1, const RoseProgram &prog2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Removes any CHECK_HANDLED instructions from the given program */
|
||||||
|
void stripCheckHandledInstruction(RoseProgram &prog);
|
||||||
|
|
||||||
/** Returns true if the program may read the the interpreter's work_done flag */
|
/** Returns true if the program may read the the interpreter's work_done flag */
|
||||||
bool reads_work_done_flag(const RoseProgram &prog);
|
bool reads_work_done_flag(const RoseProgram &prog);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user