rose: use lookarounds to implement benefits masks

This replaces the CHECK_LIT_MASK instruction.
This commit is contained in:
Justin Viiret 2016-08-08 15:39:43 +10:00 committed by Matthew Barr
parent b96d5c23d1
commit 4ce306864e

View File

@ -3352,6 +3352,37 @@ bool makeRoleMask32(const vector<LookEntry> &look,
return true; return true;
} }
/**
* Builds a lookaround instruction, or an appropriate specialization if one is
* available.
*/
static
void makeLookaroundInstruction(build_context &bc, const vector<LookEntry> &look,
vector<RoseInstruction> &program) {
assert(!look.empty());
if (makeRoleByte(look, program)) {
return;
}
if (makeRoleMask(look, program)) {
return;
}
if (makeRoleMask32(look, program)) {
return;
}
u32 look_idx = addLookaround(bc, look);
u32 look_count = verify_u32(look.size());
auto ri = RoseInstruction(ROSE_INSTR_CHECK_LOOKAROUND,
JumpTarget::NEXT_BLOCK);
ri.u.checkLookaround.index = look_idx;
ri.u.checkLookaround.count = look_count;
program.push_back(ri);
}
static static
void makeRoleLookaround(RoseBuildImpl &build, build_context &bc, RoseVertex v, void makeRoleLookaround(RoseBuildImpl &build, build_context &bc, RoseVertex v,
vector<RoseInstruction> &program) { vector<RoseInstruction> &program) {
@ -3377,27 +3408,7 @@ void makeRoleLookaround(RoseBuildImpl &build, build_context &bc, RoseVertex v,
return; return;
} }
if (makeRoleByte(look, program)) { makeLookaroundInstruction(bc, look, program);
return;
}
if (makeRoleMask(look, program)) {
return;
}
if (makeRoleMask32(look, program)) {
return;
}
DEBUG_PRINTF("role has lookaround\n");
u32 look_idx = addLookaround(bc, look);
u32 look_count = verify_u32(look.size());
auto ri = RoseInstruction(ROSE_INSTR_CHECK_LOOKAROUND,
JumpTarget::NEXT_BLOCK);
ri.u.checkLookaround.index = look_idx;
ri.u.checkLookaround.count = look_count;
program.push_back(ri);
} }
static static
@ -4377,7 +4388,7 @@ void addPredBlocks(build_context &bc,
vector<RoseInstruction> &program) { vector<RoseInstruction> &program) {
const size_t num_preds = predProgramLists.size(); const size_t num_preds = predProgramLists.size();
if (num_preds == 0) { if (num_preds == 0) {
program = flattenProgram({program}); program.emplace_back(ROSE_INSTR_END);
return; return;
} }
@ -4420,6 +4431,10 @@ vector<RoseInstruction> makeSparseIterProgram(build_context &bc,
program.insert(end(program), begin(root_program), end(root_program)); program.insert(end(program), begin(root_program), end(root_program));
} }
assert(!program.empty());
assert(program.back().code() == ROSE_INSTR_END);
program.pop_back();
program = flattenProgram({program});
return program; return program;
} }
@ -4473,7 +4488,8 @@ void makeGroupCheckInstruction(const RoseBuildImpl &build, u32 final_id,
} }
static static
void makeCheckLitMaskInstruction(const RoseBuildImpl &build, u32 final_id, void makeCheckLitMaskInstruction(const RoseBuildImpl &build, build_context &bc,
u32 final_id,
vector<RoseInstruction> &program) { vector<RoseInstruction> &program) {
assert(contains(build.final_id_to_literal, final_id)); assert(contains(build.final_id_to_literal, final_id));
const auto &lit_infos = getLiteralInfoByFinalId(build, final_id); const auto &lit_infos = getLiteralInfoByFinalId(build, final_id);
@ -4483,7 +4499,7 @@ void makeCheckLitMaskInstruction(const RoseBuildImpl &build, u32 final_id,
return; return;
} }
auto ri = RoseInstruction(ROSE_INSTR_CHECK_LIT_MASK); vector<LookEntry> look;
assert(build.final_id_to_literal.at(final_id).size() == 1); assert(build.final_id_to_literal.at(final_id).size() == 1);
u32 lit_id = *build.final_id_to_literal.at(final_id).begin(); u32 lit_id = *build.final_id_to_literal.at(final_id).begin();
@ -4491,14 +4507,16 @@ void makeCheckLitMaskInstruction(const RoseBuildImpl &build, u32 final_id,
DEBUG_PRINTF("building mask for lit %u (final id %u) %s\n", lit_id, DEBUG_PRINTF("building mask for lit %u (final id %u) %s\n", lit_id,
final_id, dumpString(s).c_str()); final_id, dumpString(s).c_str());
assert(s.length() <= MAX_MASK2_WIDTH); assert(s.length() <= MAX_MASK2_WIDTH);
u32 i = 0; s32 i = 0 - s.length();
for (const auto &e : s) { for (const auto &e : s) {
ri.u.checkLitMask.and_mask.a8[i] = e.nocase ? 0 : CASE_BIT; if (!e.nocase) {
ri.u.checkLitMask.cmp_mask.a8[i] = e.nocase ? 0 : (CASE_BIT & e.c); look.emplace_back(verify_s8(i), e);
}
i++; i++;
} }
program.push_back(move(ri)); assert(!look.empty());
makeLookaroundInstruction(bc, look, program);
} }
static static
@ -4662,7 +4680,7 @@ vector<RoseInstruction> buildLitInitialProgram(RoseBuildImpl &build,
DEBUG_PRINTF("final_id %u\n", final_id); DEBUG_PRINTF("final_id %u\n", final_id);
// Check lit mask. // Check lit mask.
makeCheckLitMaskInstruction(build, final_id, pre_program); makeCheckLitMaskInstruction(build, bc, final_id, pre_program);
// Check literal groups. This is an optimisation that we only perform for // Check literal groups. This is an optimisation that we only perform for
// delayed literals, as their groups may be switched off; ordinarily, we // delayed literals, as their groups may be switched off; ordinarily, we
@ -4771,7 +4789,7 @@ u32 buildDelayRebuildProgram(RoseBuildImpl &build, build_context &bc,
} }
vector<RoseInstruction> program; vector<RoseInstruction> program;
makeCheckLitMaskInstruction(build, final_id, program); makeCheckLitMaskInstruction(build, bc, final_id, program);
makePushDelayedInstructions(build, final_id, program); makePushDelayedInstructions(build, final_id, program);
assert(!program.empty()); assert(!program.empty());
program = flattenProgram({program}); program = flattenProgram({program});