VarAction2: Fix dead store elimination through randomised sprite groups

This commit is contained in:
Jonathan G Rennison
2022-06-01 22:36:04 +01:00
parent ce98daedce
commit 3c9201ebd5

View File

@@ -51,6 +51,7 @@
#include "newgrf_roadstop.h" #include "newgrf_roadstop.h"
#include "debug_settings.h" #include "debug_settings.h"
#include "core/arena_alloc.hpp" #include "core/arena_alloc.hpp"
#include "core/y_combinator.hpp"
#include "table/strings.h" #include "table/strings.h"
#include "table/build_industry.h" #include "table/build_industry.h"
@@ -5736,8 +5737,15 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
if (adjust.variable == 0x7E) { if (adjust.variable == 0x7E) {
state.seen_procedure_call = true; state.seen_procedure_call = true;
reset_store_values(); reset_store_values();
if (adjust.subroutine != nullptr && adjust.subroutine->type == SGT_DETERMINISTIC) { auto handle_group = y_combinator([&](auto handle_group, const SpriteGroup *sg) -> void {
VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(adjust.subroutine, false); if (sg == nullptr) return;
if (sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
handle_group(group);
}
} else if (sg->type == SGT_DETERMINISTIC) {
VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sg, false);
if (var_tracking != nullptr) { if (var_tracking != nullptr) {
std::bitset<256> bits = var_tracking->in; std::bitset<256> bits = var_tracking->in;
for (auto &it : state.temp_stores) { for (auto &it : state.temp_stores) {
@@ -5745,7 +5753,9 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
} }
state.GetVarTracking(group)->in |= bits; state.GetVarTracking(group)->in |= bits;
} }
}; }
});
handle_group(adjust.subroutine);
} }
} else { } else {
if (adjust.and_mask == 0 && IsEvalAdjustWithZeroRemovable(adjust.operation)) { if (adjust.and_mask == 0 && IsEvalAdjustWithZeroRemovable(adjust.operation)) {
@@ -6023,7 +6033,17 @@ static void CheckDeterministicSpriteGroupOutputVarBits(const DeterministicSprite
static void RecursiveDisallowDSEForProcedure(const SpriteGroup *group) static void RecursiveDisallowDSEForProcedure(const SpriteGroup *group)
{ {
if (group == nullptr || group->type != SGT_DETERMINISTIC) return; if (group == nullptr) return;
if (group->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)group;
for (const auto &g : rsg->groups) {
RecursiveDisallowDSEForProcedure(g);
}
return;
}
if (group->type != SGT_DETERMINISTIC) return;
const DeterministicSpriteGroup *sub = static_cast<const DeterministicSpriteGroup *>(group); const DeterministicSpriteGroup *sub = static_cast<const DeterministicSpriteGroup *>(group);
VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sub, true); VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sub, true);
@@ -6062,9 +6082,17 @@ static void CheckDeterministicSpriteGroupOutputVarBits(const DeterministicSprite
if (adjust.variable == 0x7D && adjust.parameter < 0x100) { if (adjust.variable == 0x7D && adjust.parameter < 0x100) {
bits.set(adjust.parameter, true); bits.set(adjust.parameter, true);
} }
if (adjust.variable == 0x7E && adjust.subroutine != nullptr && adjust.subroutine->type == SGT_DETERMINISTIC) { if (adjust.variable == 0x7E) {
/* procedure call */ /* procedure call */
const DeterministicSpriteGroup *sub = static_cast<const DeterministicSpriteGroup *>(adjust.subroutine); auto handle_group = y_combinator([&](auto handle_group, 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_group(group);
}
} else if (sg->type == SGT_DETERMINISTIC) {
const DeterministicSpriteGroup *sub = static_cast<const DeterministicSpriteGroup *>(sg);
VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sub, true); VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sub, true);
if (sub->calculated_result) { if (sub->calculated_result) {
std::bitset<256> new_out = bits | var_tracking->out; std::bitset<256> new_out = bits | var_tracking->out;
@@ -6077,6 +6105,9 @@ static void CheckDeterministicSpriteGroupOutputVarBits(const DeterministicSprite
} }
bits |= var_tracking->in; bits |= var_tracking->in;
} }
});
handle_group(adjust.subroutine);
}
} }
if (dse && add_to_dse) _cur.dead_store_elimination_candidates.push_back(const_cast<DeterministicSpriteGroup *>(group)); if (dse && add_to_dse) _cur.dead_store_elimination_candidates.push_back(const_cast<DeterministicSpriteGroup *>(group));
} }
@@ -6113,11 +6144,17 @@ static void OptimiseVarAction2DeterministicSpriteGroup(VarAction2OptimiseState &
std::bitset<256> bits; std::bitset<256> bits;
if (!group->calculated_result) { if (!group->calculated_result) {
auto handle_group = [&](const SpriteGroup *sg) { auto handle_group = y_combinator([&](auto handle_group, const SpriteGroup *sg) -> void {
if (sg != nullptr && sg->type == SGT_DETERMINISTIC) { if (sg != nullptr && sg->type == SGT_DETERMINISTIC) {
VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sg, false); VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sg, false);
if (var_tracking != nullptr) bits |= var_tracking->in; if (var_tracking != nullptr) bits |= var_tracking->in;
} }
if (sg != nullptr && sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
handle_group(group);
}
}
if (sg != nullptr && sg->type == SGT_TILELAYOUT) { if (sg != nullptr && sg->type == SGT_TILELAYOUT) {
const TileLayoutSpriteGroup *tlsg = (const TileLayoutSpriteGroup*)sg; const TileLayoutSpriteGroup *tlsg = (const TileLayoutSpriteGroup*)sg;
if (tlsg->dts.registers != nullptr) { if (tlsg->dts.registers != nullptr) {
@@ -6152,7 +6189,7 @@ static void OptimiseVarAction2DeterministicSpriteGroup(VarAction2OptimiseState &
bits.set(ipsg->again, true); bits.set(ipsg->again, true);
} }
} }
}; });
handle_group(group->default_group); handle_group(group->default_group);
for (const auto &range : group->ranges) { for (const auto &range : group->ranges) {
handle_group(range.group); handle_group(range.group);
@@ -6237,12 +6274,23 @@ static void HandleVarAction2DeadStoreElimination()
if (adjust.variable == 0x7D && adjust.parameter < 0x100) { if (adjust.variable == 0x7D && adjust.parameter < 0x100) {
bits.set(adjust.parameter, true); bits.set(adjust.parameter, true);
} }
if (adjust.variable == 0x7E && adjust.subroutine != nullptr && adjust.subroutine->type == SGT_DETERMINISTIC) { if (adjust.variable == 0x7E) {
/* procedure call */ /* procedure call */
const DeterministicSpriteGroup *sub = static_cast<const DeterministicSpriteGroup *>(adjust.subroutine); auto handle_group = y_combinator([&](auto handle_group, 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_group(group);
}
} else if (sg->type == SGT_DETERMINISTIC) {
const DeterministicSpriteGroup *sub = static_cast<const DeterministicSpriteGroup *>(sg);
VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sub, false); VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sub, false);
if (var_tracking != nullptr) bits |= var_tracking->in; if (var_tracking != nullptr) bits |= var_tracking->in;
} }
});
handle_group(adjust.subroutine);
}
i--; i--;
} }
} }