VarAction2: Handle deterministic/CB groups under real sprite groups in optimiser

See: #618
wip-string
Jonathan G Rennison 6 months ago
parent d793da4034
commit 5062b35b7d

@ -717,6 +717,65 @@ static uint TryMergeVarAction2AdjustConstantOperations(DeterministicSpriteGroupA
return 1;
}
static inline bool IsSimpleContainerSpriteGroup(const SpriteGroup *group) {
return group != nullptr && (group->type == SGT_RANDOMIZED || group->type == SGT_REAL);
}
struct SimpleContainerSpriteGroupIterator {
typedef const SpriteGroup * value_type;
typedef const SpriteGroup * *pointer;
typedef const SpriteGroup * &reference;
typedef size_t difference_type;
typedef std::forward_iterator_tag iterator_category;
explicit SimpleContainerSpriteGroupIterator(const SpriteGroup * const * current, const SpriteGroup * const * end, const SpriteGroup * const * next)
: current(current), end(end), next(next)
{
this->ValidateIndex();
};
bool operator==(const SimpleContainerSpriteGroupIterator &other) const { return this->current == other.current; }
bool operator!=(const SimpleContainerSpriteGroupIterator &other) const { return !(*this == other); }
const SpriteGroup *operator*() const { return *this->current; }
SimpleContainerSpriteGroupIterator &operator++() { ++this->current; this->ValidateIndex(); return *this; }
private:
const SpriteGroup * const * current;
const SpriteGroup * const * end;
const SpriteGroup * const * next;
void ValidateIndex()
{
if (this->current == this->end) this->current = this->next;
}
};
/* Wrapper to iterate the sprite groups within SGT_RANDOMIZED or SGT_REAL groups */
struct IterateSimpleContainerSpriteGroup {
std::array<const SpriteGroup * const *, 2> begin_ptr{};
std::array<const SpriteGroup * const *, 2> end_ptr{};
IterateSimpleContainerSpriteGroup(const SpriteGroup *sg)
{
if (sg == nullptr) return;
if (sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
this->begin_ptr[0] = rsg->groups.data();
this->end_ptr[0] = rsg->groups.data() + rsg->groups.size();
}
if (sg->type == SGT_REAL) {
const RealSpriteGroup *rsg = (const RealSpriteGroup*)sg;
this->begin_ptr[0] = rsg->loaded.data();
this->end_ptr[0] = rsg->loaded.data() + rsg->loaded.size();
this->begin_ptr[1] = rsg->loading.data();
this->end_ptr[1] = rsg->loading.data() + rsg->loading.size();
}
}
SimpleContainerSpriteGroupIterator begin() { return SimpleContainerSpriteGroupIterator(this->begin_ptr[0], this->end_ptr[0], this->begin_ptr[1]); }
SimpleContainerSpriteGroupIterator end() { return SimpleContainerSpriteGroupIterator(this->end_ptr[1], this->end_ptr[1], this->end_ptr[1]); }
};
void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const VarAction2AdjustInfo info, DeterministicSpriteGroup *group, DeterministicSpriteGroupAdjust &adjust)
{
if (unlikely(HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2))) return;
@ -1057,9 +1116,8 @@ void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const VarAction2Ad
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) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_proc_stores(group);
}
} else if (sg->type == SGT_DETERMINISTIC) {
@ -1099,9 +1157,8 @@ void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const VarAction2Ad
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) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_group(group);
}
} else if (sg->type == SGT_DETERMINISTIC) {
@ -1729,14 +1786,14 @@ struct CheckDeterministicSpriteGroupOutputVarBitsProcedureHandler {
bool ProcessGroup(const SpriteGroup *sg, std::bitset<256> *input_bits, bool top_level)
{
if (sg == nullptr) return true;
if (sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
if (rsg->groups.empty()) return true;
if (IsSimpleContainerSpriteGroup(sg)) {
bool non_handled = false;
for (const auto &group : rsg->groups) {
uint count = 0;
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
count++;
non_handled |= this->ProcessGroup(group, input_bits, top_level);
}
return non_handled;
return non_handled || count == 0;
} else if (sg->type == SGT_DETERMINISTIC) {
const DeterministicSpriteGroup *sub = static_cast<const DeterministicSpriteGroup *>(sg);
@ -1923,9 +1980,8 @@ static bool OptimiseVarAction2DeterministicSpriteGroupExpensiveVarsInner(Determi
VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(sg, false);
if (var_tracking != nullptr) usable_vars &= ~var_tracking->in;
}
if (sg != nullptr && sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_group(group);
}
}
@ -2123,9 +2179,8 @@ static VarAction2ProcedureAnnotation *OptimiseVarAction2GetFilledProcedureAnnota
if (is_new) {
auto handle_group_contents = y_combinator([&](auto handle_group_contents, const SpriteGroup *sg) -> void {
if (sg == nullptr || anno->unskippable) return;
if (sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_group_contents(group);
}
@ -2282,9 +2337,8 @@ static void OptimiseVarAction2DeterministicSpriteGroupPopulateLastVarReadAnnotat
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) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_group(group);
}
@ -2622,9 +2676,8 @@ void OptimiseVarAction2DeterministicSpriteGroup(VarAction2OptimiseState &state,
state.have_cb_handler = true;
}
}
if (sg != nullptr && sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_group(group, state);
}
}
@ -3024,9 +3077,8 @@ static std::bitset<256> HandleVarAction2DeadStoreElimination(DeterministicSprite
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) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_group(group);
}
} else if (sg->type == SGT_DETERMINISTIC) {
@ -3110,9 +3162,8 @@ void HandleVarAction2OptimisationPasses()
var_tracking->out |= targ_var_tracking->in;
}
}
if (sg != nullptr && sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
handle_group(group);
}
}
@ -3172,9 +3223,8 @@ const SpriteGroup *PruneTargetSpriteGroup(const SpriteGroup *result)
auto need_var1C = y_combinator([&](auto need_var1C, const SpriteGroup *sg) -> bool {
if (sg == nullptr) return false;
if (sg->type == SGT_RANDOMIZED) {
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
for (const auto &group : rsg->groups) {
if (IsSimpleContainerSpriteGroup(sg)) {
for (const auto &group : IterateSimpleContainerSpriteGroup(sg)) {
if (need_var1C(group)) return true;
}
} else if (sg->type == SGT_DETERMINISTIC) {

Loading…
Cancel
Save