VarAction2: Save/restore inference when going back to previous op with side effects

This commit is contained in:
Jonathan G Rennison
2022-06-08 21:05:33 +01:00
parent 376b434d53
commit 0484fbf941

View File

@@ -54,6 +54,7 @@
#include "core/arena_alloc.hpp" #include "core/arena_alloc.hpp"
#include "core/y_combinator.hpp" #include "core/y_combinator.hpp"
#include "core/container_func.hpp" #include "core/container_func.hpp"
#include "scope.h"
#include "table/strings.h" #include "table/strings.h"
#include "table/build_industry.h" #include "table/build_industry.h"
@@ -5652,10 +5653,17 @@ struct VarAction2TempStoreInference {
VarAction2TempStoreInferenceVarSource var_source; VarAction2TempStoreInferenceVarSource var_source;
}; };
struct VarAction2InferenceBackup {
VarAction2AdjustInferenceFlags inference = VA2AIF_NONE;
uint32 current_constant = 0;
uint adjust_size = 0;
};
struct VarAction2OptimiseState { struct VarAction2OptimiseState {
VarAction2AdjustInferenceFlags inference = VA2AIF_NONE; VarAction2AdjustInferenceFlags inference = VA2AIF_NONE;
uint32 current_constant = 0; uint32 current_constant = 0;
btree::btree_map<uint8, VarAction2TempStoreInference> temp_stores; btree::btree_map<uint8, VarAction2TempStoreInference> temp_stores;
VarAction2InferenceBackup inference_backup;
VarAction2GroupVariableTracking *var_tracking = nullptr; VarAction2GroupVariableTracking *var_tracking = nullptr;
bool seen_procedure_call = false; bool seen_procedure_call = false;
bool check_expensive_vars = false; bool check_expensive_vars = false;
@@ -5772,6 +5780,25 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
{ {
if (unlikely(HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2))) return; if (unlikely(HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2))) return;
auto guard = scope_guard([&]() {
if (!group->adjusts.empty()) {
const DeterministicSpriteGroupAdjust &adjust = group->adjusts.back();
if (adjust.variable == 0x7E || IsEvalAdjustWithSideEffects(adjust.operation)) {
/* save inference state */
state.inference_backup.adjust_size = (uint)group->adjusts.size();
state.inference_backup.inference = state.inference;
state.inference_backup.current_constant = state.current_constant;
}
}
});
auto try_restore_inference_backup = [&]() {
if (state.inference_backup.adjust_size != 0 && state.inference_backup.adjust_size == (uint)group->adjusts.size()) {
state.inference = state.inference_backup.inference;
state.current_constant = state.inference_backup.current_constant;
}
};
VarAction2AdjustInferenceFlags prev_inference = state.inference; VarAction2AdjustInferenceFlags prev_inference = state.inference;
state.inference = VA2AIF_NONE; state.inference = VA2AIF_NONE;
@@ -5807,15 +5834,18 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
break; break;
} }
} }
DeterministicSpriteGroupAdjust &replacement = group->adjusts.emplace_back(); if (constant != 0 || !group->adjusts.empty()) {
replacement.operation = DSGA_OP_RST; DeterministicSpriteGroupAdjust &replacement = group->adjusts.emplace_back();
replacement.variable = 0x1A; replacement.operation = DSGA_OP_RST;
replacement.shift_num = 0; replacement.variable = 0x1A;
replacement.type = DSGA_TYPE_NONE; replacement.shift_num = 0;
replacement.and_mask = constant; replacement.type = DSGA_TYPE_NONE;
replacement.add_val = 0; replacement.and_mask = constant;
replacement.divmod_val = 0; replacement.add_val = 0;
state.inference = VA2AIF_PREV_MASK_ADJUST | VA2AIF_HAVE_CONSTANT; replacement.divmod_val = 0;
state.inference = VA2AIF_PREV_MASK_ADJUST;
}
state.inference = VA2AIF_HAVE_CONSTANT;
add_inferences_from_mask(constant); add_inferences_from_mask(constant);
state.current_constant = constant; state.current_constant = constant;
}; };
@@ -5936,6 +5966,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
break; break;
} }
} }
try_restore_inference_backup();
current.operation = DSGA_OP_RST; current.operation = DSGA_OP_RST;
current.adjust_flags = DSGAF_NONE; current.adjust_flags = DSGAF_NONE;
group->adjusts.push_back(current); group->adjusts.push_back(current);