VarAction2: Add flags to skip adjust if value is 0 or LSB set
This commit is contained in:
@@ -5852,6 +5852,10 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adjust.variable != 0x7E && IsEvalAdjustWithZeroLastValueAlwaysZero(adjust.operation)) {
|
||||||
|
adjust.adjust_flags |= DSGAF_SKIP_ON_ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
if ((prev_inference & VA2AIF_PREV_TERNARY) && adjust.variable == 0x1A && IsEvalAdjustUsableForConstantPropagation(adjust.operation)) {
|
if ((prev_inference & VA2AIF_PREV_TERNARY) && adjust.variable == 0x1A && IsEvalAdjustUsableForConstantPropagation(adjust.operation)) {
|
||||||
/* Propagate constant operation back into previous ternary */
|
/* Propagate constant operation back into previous ternary */
|
||||||
DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2];
|
DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2];
|
||||||
@@ -5862,7 +5866,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
} else if ((prev_inference & VA2AIF_HAVE_CONSTANT) && adjust.variable == 0x1A && IsEvalAdjustUsableForConstantPropagation(adjust.operation)) {
|
} else if ((prev_inference & VA2AIF_HAVE_CONSTANT) && adjust.variable == 0x1A && IsEvalAdjustUsableForConstantPropagation(adjust.operation)) {
|
||||||
/* Reduce constant operation on previous constant */
|
/* Reduce constant operation on previous constant */
|
||||||
replace_with_constant_load(EvaluateDeterministicSpriteGroupAdjust(group->size, adjust, nullptr, state.current_constant, UINT_MAX));
|
replace_with_constant_load(EvaluateDeterministicSpriteGroupAdjust(group->size, adjust, nullptr, state.current_constant, UINT_MAX));
|
||||||
} else if ((prev_inference & VA2AIF_HAVE_CONSTANT) && state.current_constant == 0 && adjust.variable != 0x7E && IsEvalAdjustWithZeroLastValueAlwaysZero(adjust.operation)) {
|
} else if ((prev_inference & VA2AIF_HAVE_CONSTANT) && state.current_constant == 0 && (adjust.adjust_flags & DSGAF_SKIP_ON_ZERO)) {
|
||||||
/* Remove operation which does nothing when applied to 0 */
|
/* Remove operation which does nothing when applied to 0 */
|
||||||
group->adjusts.pop_back();
|
group->adjusts.pop_back();
|
||||||
state.inference = prev_inference;
|
state.inference = prev_inference;
|
||||||
@@ -5880,6 +5884,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
current.operation = DSGA_OP_RST;
|
current.operation = DSGA_OP_RST;
|
||||||
|
current.adjust_flags = DSGAF_NONE;
|
||||||
group->adjusts.push_back(current);
|
group->adjusts.push_back(current);
|
||||||
OptimiseVarAction2Adjust(state, feature, varsize, group, group->adjusts.back());
|
OptimiseVarAction2Adjust(state, feature, varsize, group, group->adjusts.back());
|
||||||
return;
|
return;
|
||||||
@@ -5917,6 +5922,9 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
} else if (adjust.operation == DSGA_OP_OR || adjust.operation == DSGA_OP_XOR || adjust.operation == DSGA_OP_AND) {
|
} else if (adjust.operation == DSGA_OP_OR || adjust.operation == DSGA_OP_XOR || adjust.operation == DSGA_OP_AND) {
|
||||||
state.inference |= (prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO));
|
state.inference |= (prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO));
|
||||||
}
|
}
|
||||||
|
if (adjust.operation == DSGA_OP_OR && (prev_inference & VA2AIF_ONE_OR_ZERO) && adjust.variable != 0x7E) {
|
||||||
|
adjust.adjust_flags |= DSGAF_SKIP_ON_LSB_SET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (adjust.and_mask == 0 && IsEvalAdjustWithZeroRemovable(adjust.operation)) {
|
if (adjust.and_mask == 0 && IsEvalAdjustWithZeroRemovable(adjust.operation)) {
|
||||||
@@ -5936,6 +5944,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
/* Convert: store, load var, commutative op on stored --> (dead) store, commutative op var */
|
/* Convert: store, load var, commutative op on stored --> (dead) store, commutative op var */
|
||||||
prev.operation = adjust.operation;
|
prev.operation = adjust.operation;
|
||||||
group->adjusts.pop_back();
|
group->adjusts.pop_back();
|
||||||
|
state.inference = non_const_var_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO);
|
||||||
OptimiseVarAction2Adjust(state, feature, varsize, group, group->adjusts.back());
|
OptimiseVarAction2Adjust(state, feature, varsize, group, group->adjusts.back());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5952,6 +5961,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
/* Convert: store, load var, subtract stored --> (dead) store, reverse subtract var */
|
/* Convert: store, load var, subtract stored --> (dead) store, reverse subtract var */
|
||||||
prev.operation = DSGA_OP_RSUB;
|
prev.operation = DSGA_OP_RSUB;
|
||||||
group->adjusts.pop_back();
|
group->adjusts.pop_back();
|
||||||
|
state.inference = non_const_var_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO);
|
||||||
OptimiseVarAction2Adjust(state, feature, varsize, group, group->adjusts.back());
|
OptimiseVarAction2Adjust(state, feature, varsize, group, group->adjusts.back());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -6068,6 +6078,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
}
|
}
|
||||||
if (adjust.and_mask <= 1) state.inference = prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO);
|
if (adjust.and_mask <= 1) state.inference = prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO);
|
||||||
state.inference |= prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO) & non_const_var_inference;
|
state.inference |= prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO) & non_const_var_inference;
|
||||||
|
if ((non_const_var_inference & VA2AIF_ONE_OR_ZERO) || (adjust.and_mask <= 1)) adjust.adjust_flags |= DSGAF_SKIP_ON_LSB_SET;
|
||||||
break;
|
break;
|
||||||
case DSGA_OP_XOR:
|
case DSGA_OP_XOR:
|
||||||
if (adjust.variable == 0x1A && adjust.shift_num == 0 && group->adjusts.size() >= 2) {
|
if (adjust.variable == 0x1A && adjust.shift_num == 0 && group->adjusts.size() >= 2) {
|
||||||
@@ -6081,6 +6092,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
}
|
}
|
||||||
if (prev.operation == DSGA_OP_UMIN && prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == 1) {
|
if (prev.operation == DSGA_OP_UMIN && prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == 1) {
|
||||||
prev.operation = DSGA_OP_TERNARY;
|
prev.operation = DSGA_OP_TERNARY;
|
||||||
|
prev.adjust_flags = DSGAF_NONE;
|
||||||
prev.and_mask = 0;
|
prev.and_mask = 0;
|
||||||
prev.add_val = 1;
|
prev.add_val = 1;
|
||||||
group->adjusts.pop_back();
|
group->adjusts.pop_back();
|
||||||
@@ -6097,6 +6109,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
if (prev.operation == DSGA_OP_OR && prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == adjust.and_mask) {
|
if (prev.operation == DSGA_OP_OR && prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == adjust.and_mask) {
|
||||||
prev.operation = DSGA_OP_AND;
|
prev.operation = DSGA_OP_AND;
|
||||||
prev.and_mask = ~prev.and_mask;
|
prev.and_mask = ~prev.and_mask;
|
||||||
|
prev.adjust_flags = DSGAF_NONE;
|
||||||
group->adjusts.pop_back();
|
group->adjusts.pop_back();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -6108,6 +6121,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
if ((prev_inference & VA2AIF_ONE_OR_ZERO) && adjust.variable == 0x1A && adjust.shift_num == 0 && group->adjusts.size() >= 2) {
|
if ((prev_inference & VA2AIF_ONE_OR_ZERO) && adjust.variable == 0x1A && adjust.shift_num == 0 && group->adjusts.size() >= 2) {
|
||||||
/* Found a ternary operator */
|
/* Found a ternary operator */
|
||||||
adjust.operation = DSGA_OP_TERNARY;
|
adjust.operation = DSGA_OP_TERNARY;
|
||||||
|
adjust.adjust_flags = DSGAF_NONE;
|
||||||
while (group->adjusts.size() > 1) {
|
while (group->adjusts.size() > 1) {
|
||||||
/* Merge with previous if applicable */
|
/* Merge with previous if applicable */
|
||||||
const DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2];
|
const DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2];
|
||||||
@@ -6537,6 +6551,7 @@ static void OptimiseVarAction2DeterministicSpriteGroupSimplifyStores(Determinist
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
const DeterministicSpriteGroupAdjust &src = group->adjusts[src_adjust];
|
const DeterministicSpriteGroupAdjust &src = group->adjusts[src_adjust];
|
||||||
adjust.operation = DSGA_OP_STO_NC;
|
adjust.operation = DSGA_OP_STO_NC;
|
||||||
|
adjust.adjust_flags = DSGAF_NONE;
|
||||||
adjust.add_val = adjust.and_mask;
|
adjust.add_val = adjust.and_mask;
|
||||||
adjust.variable = src.variable;
|
adjust.variable = src.variable;
|
||||||
adjust.parameter = src.parameter;
|
adjust.parameter = src.parameter;
|
||||||
|
@@ -223,6 +223,9 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con
|
|||||||
ScopeResolver *scope = object.GetScope(this->var_scope);
|
ScopeResolver *scope = object.GetScope(this->var_scope);
|
||||||
|
|
||||||
for (const auto &adjust : this->adjusts) {
|
for (const auto &adjust : this->adjusts) {
|
||||||
|
if ((adjust.adjust_flags & DSGAF_SKIP_ON_ZERO) && (last_value == 0)) continue;
|
||||||
|
if ((adjust.adjust_flags & DSGAF_SKIP_ON_LSB_SET) && (last_value & 1) != 0) continue;
|
||||||
|
|
||||||
/* Try to get the variable. We shall assume it is available, unless told otherwise. */
|
/* Try to get the variable. We shall assume it is available, unless told otherwise. */
|
||||||
GetVariableExtra extra(adjust.and_mask << adjust.shift_num);
|
GetVariableExtra extra(adjust.and_mask << adjust.shift_num);
|
||||||
if (adjust.variable == 0x7E) {
|
if (adjust.variable == 0x7E) {
|
||||||
@@ -772,8 +775,19 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint
|
|||||||
/* Temp storage load */
|
/* Temp storage load */
|
||||||
highlight_tag = (1 << 16) | (adjust.parameter & 0xFFFF);
|
highlight_tag = (1 << 16) | (adjust.parameter & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto append_flags = [&]() {
|
||||||
|
if (adjust.adjust_flags & DSGAF_SKIP_ON_ZERO) {
|
||||||
|
p += seprintf(p, lastof(this->buffer), ", skip on zero");
|
||||||
|
}
|
||||||
|
if (adjust.adjust_flags & DSGAF_SKIP_ON_LSB_SET) {
|
||||||
|
p += seprintf(p, lastof(this->buffer), ", skip on LSB set");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (adjust.operation == DSGA_OP_TERNARY) {
|
if (adjust.operation == DSGA_OP_TERNARY) {
|
||||||
p += seprintf(p, lastof(this->buffer), "%*sTERNARY: true: %X, false: %X", padding, "", adjust.and_mask, adjust.add_val);
|
p += seprintf(p, lastof(this->buffer), "%*sTERNARY: true: %X, false: %X", padding, "", adjust.and_mask, adjust.add_val);
|
||||||
|
append_flags();
|
||||||
print();
|
print();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -808,6 +822,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint
|
|||||||
}
|
}
|
||||||
p += seprintf(p, lastof(this->buffer), ", op: ");
|
p += seprintf(p, lastof(this->buffer), ", op: ");
|
||||||
p = GetAdjustOperationName(p, lastof(this->buffer), adjust.operation);
|
p = GetAdjustOperationName(p, lastof(this->buffer), adjust.operation);
|
||||||
|
append_flags();
|
||||||
print();
|
print();
|
||||||
if (adjust.variable == 0x7E && adjust.subroutine != nullptr) {
|
if (adjust.variable == 0x7E && adjust.subroutine != nullptr) {
|
||||||
this->DumpSpriteGroup(adjust.subroutine, padding + 5, 0);
|
this->DumpSpriteGroup(adjust.subroutine, padding + 5, 0);
|
||||||
|
@@ -202,6 +202,13 @@ enum DeterministicSpriteGroupAdjustOperation : uint8 {
|
|||||||
static_assert((DSGA_OP_SLT ^ 1) == DSGA_OP_SGE);
|
static_assert((DSGA_OP_SLT ^ 1) == DSGA_OP_SGE);
|
||||||
static_assert((DSGA_OP_SLE ^ 1) == DSGA_OP_SGT);
|
static_assert((DSGA_OP_SLE ^ 1) == DSGA_OP_SGT);
|
||||||
|
|
||||||
|
enum DeterministicSpriteGroupAdjustFlags : uint8 {
|
||||||
|
DSGAF_NONE = 0,
|
||||||
|
DSGAF_SKIP_ON_ZERO = 1 << 0,
|
||||||
|
DSGAF_SKIP_ON_LSB_SET = 1 << 1,
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_AS_BIT_SET(DeterministicSpriteGroupAdjustFlags);
|
||||||
|
|
||||||
inline bool IsEvalAdjustWithZeroRemovable(DeterministicSpriteGroupAdjustOperation op)
|
inline bool IsEvalAdjustWithZeroRemovable(DeterministicSpriteGroupAdjustOperation op)
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -333,6 +340,7 @@ struct DeterministicSpriteGroupAdjust {
|
|||||||
DeterministicSpriteGroupAdjustType type;
|
DeterministicSpriteGroupAdjustType type;
|
||||||
uint16 variable;
|
uint16 variable;
|
||||||
byte shift_num;
|
byte shift_num;
|
||||||
|
DeterministicSpriteGroupAdjustFlags adjust_flags = DSGAF_NONE;
|
||||||
uint32 parameter; ///< Used for variables between 0x60 and 0x7F inclusive.
|
uint32 parameter; ///< Used for variables between 0x60 and 0x7F inclusive.
|
||||||
uint32 and_mask;
|
uint32 and_mask;
|
||||||
uint32 add_val;
|
uint32 add_val;
|
||||||
@@ -340,7 +348,6 @@ struct DeterministicSpriteGroupAdjust {
|
|||||||
const SpriteGroup *subroutine;
|
const SpriteGroup *subroutine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DeterministicSpriteGroupRange {
|
struct DeterministicSpriteGroupRange {
|
||||||
const SpriteGroup *group;
|
const SpriteGroup *group;
|
||||||
uint32 low;
|
uint32 low;
|
||||||
|
Reference in New Issue
Block a user