VarAction2: Track which temp stores may be overwritten by procedures

Instead of treating procedures as an unpredictable store
pull/428/head
Jonathan G Rennison 2 years ago
parent 06cc71b6c5
commit e143ab06d8

@ -6711,7 +6711,50 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
/* Procedure call or complex adjustment */
if (adjust.operation == DSGA_OP_STO) handle_unpredictable_temp_store();
if (adjust.variable == 0x7E) {
reset_store_values();
std::bitset<256> seen_stores;
bool seen_unpredictable_store = false;
bool seen_special_store = false;
bool seen_perm_store = false;
auto handle_proc_stores = y_combinator([&](auto handle_proc_stores, const SpriteGroup *sg) -> void {
if (sg == nullptr) return;
if (sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
handle_proc_stores(group);
}
} else if (sg->type == SGT_DETERMINISTIC) {
const DeterministicSpriteGroup *dsg = (const DeterministicSpriteGroup*)sg;
for (const DeterministicSpriteGroupAdjust &adjust : dsg->adjusts) {
if (adjust.variable == 0x7E) {
handle_proc_stores(adjust.subroutine);
}
if (adjust.operation == DSGA_OP_STO) {
if (adjust.type == DSGA_TYPE_NONE && adjust.variable == 0x1A && adjust.shift_num == 0) {
/* Temp store */
if (adjust.and_mask < 0x100) {
seen_stores.set(adjust.and_mask, true);
} else {
seen_special_store = true;
}
} else {
/* Unpredictable store */
seen_unpredictable_store = true;
}
}
if (adjust.operation == DSGA_OP_STO_NC) {
if (adjust.divmod_val < 0x100) {
seen_stores.set(adjust.divmod_val, true);
} else {
seen_special_store = true;
}
}
if (adjust.operation == DSGA_OP_STOP) {
seen_perm_store = true;
}
}
}
});
auto handle_group = y_combinator([&](auto handle_group, const SpriteGroup *sg) -> void {
if (sg == nullptr) return;
if (sg->type == SGT_RANDOMIZED) {
@ -6731,9 +6774,35 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
if (!state.seen_procedure_call && ((const DeterministicSpriteGroup*)sg)->dsg_flags & DSGF_REQUIRES_VAR1C) {
group->dsg_flags |= DSGF_REQUIRES_VAR1C;
}
handle_proc_stores(sg);
}
});
handle_group(adjust.subroutine);
if (seen_unpredictable_store) {
reset_store_values();
} else {
for (auto &it : state.temp_stores) {
if (seen_stores[it.first]) {
it.second.inference = VA2AIF_NONE;
it.second.version++;
} else {
/* See DSGA_OP_STO handler */
if ((it.second.inference & VA2AIF_SINGLE_LOAD) && it.second.var_source.variable == 0x7D && seen_stores[it.second.var_source.parameter & 0xFF]) {
it.second.inference &= ~VA2AIF_SINGLE_LOAD;
}
if (seen_special_store && (it.second.inference & VA2AIF_SINGLE_LOAD) && it.second.var_source.variable != 0x7D) {
it.second.inference &= ~VA2AIF_SINGLE_LOAD;
}
/* See DSGA_OP_STOP handler */
if (seen_perm_store && (it.second.inference & VA2AIF_SINGLE_LOAD) && it.second.var_source.variable == 0x7C) {
it.second.inference &= ~VA2AIF_SINGLE_LOAD;
}
}
}
}
state.seen_procedure_call = true;
} else if (adjust.operation == DSGA_OP_RST) {
state.inference = VA2AIF_SINGLE_LOAD;

Loading…
Cancel
Save