diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 8d4675f910..fd9de57db2 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5652,6 +5652,7 @@ struct VarAction2TempStoreInference { VarAction2AdjustInferenceFlags inference = VA2AIF_NONE; uint32 store_constant = 0; VarAction2TempStoreInferenceVarSource var_source; + uint version = 0; }; struct VarAction2InferenceBackup { @@ -5669,6 +5670,7 @@ struct VarAction2OptimiseState { bool seen_procedure_call = false; bool check_expensive_vars = false; bool enable_dse = false; + uint default_variable_version = 0; inline VarAction2GroupVariableTracking *GetVarTracking(DeterministicSpriteGroup *group) { @@ -5765,7 +5767,7 @@ static const DeterministicSpriteGroupAdjust *GetVarAction2PreviousSingleLoadAdju /* If we passed a store perm then a load from permanent storage is not a valid previous load as we may have clobbered it */ return nullptr; } - if (prev.variable == 0x7D && prev.parameter < 0x100 && seen_stores[prev.parameter]) { + if (prev.variable == 0x7D && seen_stores[prev.parameter & 0xFF]) { /* If we passed a store then a load from that same store is not valid */ return nullptr; } @@ -5800,7 +5802,7 @@ static const DeterministicSpriteGroupAdjust *GetVarAction2PreviousSingleLoadAdju */ static void TryMergeBoolMulCombineVarAction2Adjust(std::vector &adjusts, const int adjust_index) { - uint8 store_var = adjusts[adjust_index].parameter; + uint store_var = adjusts[adjust_index].parameter; const DeterministicSpriteGroupAdjust *a1 = nullptr; const DeterministicSpriteGroupAdjust *a2 = nullptr; @@ -5823,7 +5825,7 @@ static void TryMergeBoolMulCombineVarAction2Adjust(std::vectorin.set(adjust.parameter, true); + state.GetVarTracking(group)->in.set(adjust.parameter & 0xFF, true); + adjust.parameter |= (state.default_variable_version << 8); } else { const VarAction2TempStoreInference &store = iter->second; if (store.inference & VA2AIF_HAVE_CONSTANT) { @@ -6097,6 +6102,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp adjust.shift_num += store.var_source.shift_num; continue; } + adjust.parameter |= (store.version << 8); } else { if (adjust.type == DSGA_TYPE_NONE) { non_const_var_inference = store.inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO | VA2AIF_MUL_BOOL); @@ -6105,6 +6111,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp /* Not possible to substitute this here, but it may be possible in the DSE pass */ state.enable_dse = true; } + adjust.parameter |= (store.version << 8); } } break; @@ -6137,7 +6144,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp if ((prev_inference & VA2AIF_MUL_BOOL) && (non_const_var_inference & VA2AIF_MUL_BOOL) && (adjust.operation == DSGA_OP_ADD || adjust.operation == DSGA_OP_OR || adjust.operation == DSGA_OP_XOR) && - adjust.variable == 0x7D && adjust.parameter < 0x100 && adjust.type == DSGA_TYPE_NONE && adjust.shift_num == 0 && adjust.and_mask == 0xFFFFFFFF) { + adjust.variable == 0x7D && adjust.type == DSGA_TYPE_NONE && adjust.shift_num == 0 && adjust.and_mask == 0xFFFFFFFF) { TryMergeBoolMulCombineVarAction2Adjust(group->adjusts, (int)(group->adjusts.size() - 1)); } @@ -6530,11 +6537,18 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp if (adjust.and_mask < 0x100) { for (auto &it : state.temp_stores) { /* Check if some other variable is marked as a copy of the one we are overwriting */ - if ((it.second.inference & VA2AIF_SINGLE_LOAD) && it.second.var_source.variable == 0x7D && it.second.var_source.parameter == adjust.and_mask) { + if ((it.second.inference & VA2AIF_SINGLE_LOAD) && it.second.var_source.variable == 0x7D && (it.second.var_source.parameter & 0xFF) == adjust.and_mask) { it.second.inference &= ~VA2AIF_SINGLE_LOAD; } } VarAction2TempStoreInference &store = state.temp_stores[adjust.and_mask]; + if (store.version == 0) { + /* New store */ + store.version = state.default_variable_version + 1; + } else { + /* Updating previous store */ + store.version++; + } store.inference = prev_inference & (~VA2AIF_PREV_MASK); store.store_constant = state.current_constant; if (prev_inference & VA2AIF_SINGLE_LOAD) { @@ -6569,7 +6583,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp case DSGA_OP_RST: if ((prev_inference & VA2AIF_PREV_STORE_TMP) && adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == get_full_mask() && group->adjusts.size() >= 2) { const DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; - if (prev.type == DSGA_TYPE_NONE && prev.operation == DSGA_OP_STO && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == adjust.parameter) { + if (prev.type == DSGA_TYPE_NONE && prev.operation == DSGA_OP_STO && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == (adjust.parameter & 0xFF)) { /* Redundant load from temp store after store to temp store */ group->adjusts.pop_back(); state.inference = prev_inference; @@ -6686,8 +6700,8 @@ static bool CheckDeterministicSpriteGroupOutputVarBits(const DeterministicSprite /* Unpredictable load */ bits.set(); } - if (adjust.variable == 0x7D && adjust.parameter < 0x100) { - bits.set(adjust.parameter, true); + if (adjust.variable == 0x7D && adjust.parameter) { + bits.set(adjust.parameter & 0xFF, true); } if (adjust.variable == 0x7E) { /* procedure call */ @@ -6961,6 +6975,10 @@ static void OptimiseVarAction2DeterministicSpriteGroup(VarAction2OptimiseState & { if (unlikely(HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2))) return; + for (DeterministicSpriteGroupAdjust &adjust : group->adjusts) { + if (adjust.variable == 0x7D) adjust.parameter &= 0xFF; // Clear temporary version tags + } + if (!HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2_GROUP_PRUNE) && (state.inference & VA2AIF_HAVE_CONSTANT) && !group->calculated_result) { /* Result of this sprite group is always the same, discard the unused branches */ const SpriteGroup *target = group->default_group;