VarAction2: Track which temp stores may be overwritten by procedures
Instead of treating procedures as an unpredictable store
This commit is contained in:
@@ -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;
|
||||
|
Reference in New Issue
Block a user