VarAction2: Infer ternary add result is bool if both branches are bool
This commit is contained in:
@@ -350,21 +350,9 @@ static VarAction2AdjustsBooleanInverseResult AreVarAction2AdjustsBooleanInverse(
|
||||
return VA2ABIR_NO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find and replace the result of:
|
||||
* (var * flag) + (var * !flag) with var
|
||||
* (-var * (var < 0)) + (var * !(var < 0)) with abs(var)
|
||||
* "+" may be ADD, OR or XOR.
|
||||
*/
|
||||
static bool TryMergeBoolMulCombineVarAction2Adjust(VarAction2OptimiseState &state, std::vector<DeterministicSpriteGroupAdjust> &adjusts, const int adjust_index)
|
||||
static void GetBoolMulSourceAdjusts(std::vector<DeterministicSpriteGroupAdjust> &adjusts, int start_index, uint store_var, DeterministicSpriteGroupAdjust &synth_adjust,
|
||||
VarAction2AdjustDescriptor &found1, VarAction2AdjustDescriptor &found2, uint *mul_index)
|
||||
{
|
||||
uint store_var = adjusts[adjust_index].parameter;
|
||||
|
||||
DeterministicSpriteGroupAdjust synth_adjusts[2];
|
||||
VarAction2AdjustDescriptor found_adjusts[4] = {};
|
||||
uint mul_indices[2] = {};
|
||||
|
||||
auto find_adjusts = [&](int start_index, uint save_index) {
|
||||
bool have_mul = false;
|
||||
for (int i = start_index; i >= 0; i--) {
|
||||
const DeterministicSpriteGroupAdjust &prev = adjusts[i];
|
||||
@@ -382,21 +370,21 @@ static bool TryMergeBoolMulCombineVarAction2Adjust(VarAction2OptimiseState &stat
|
||||
}
|
||||
} else if (prev.operation == DSGA_OP_MUL && !have_mul) {
|
||||
/* First source is the variable of mul, if it's a temporary storage load, try to follow it */
|
||||
mul_indices[save_index] = i;
|
||||
if (mul_index != nullptr) *mul_index = i;
|
||||
if (prev.variable == 0x7D && prev.type == DSGA_TYPE_NONE && prev.shift_num == 0 && prev.and_mask == 0xFFFFFFFF) {
|
||||
int store_index = GetVarAction2AdjustOfPreviousTempStoreSource(adjusts.data(), i - 1, (prev.parameter & 0xFF));
|
||||
if (store_index >= 1) {
|
||||
/* Found the referenced temp store, use that */
|
||||
found_adjusts[save_index * 2] = { adjusts.data(), nullptr, store_index - 1 };
|
||||
found1 = { adjusts.data(), nullptr, store_index - 1 };
|
||||
have_mul = true;
|
||||
}
|
||||
}
|
||||
if (!have_mul) {
|
||||
/* It's not a temporary storage load which can be followed, synthesise an RST */
|
||||
synth_adjusts[save_index] = prev;
|
||||
synth_adjusts[save_index].operation = DSGA_OP_RST;
|
||||
synth_adjusts[save_index].adjust_flags = DSGAF_NONE;
|
||||
found_adjusts[save_index * 2] = { adjusts.data(), synth_adjusts + save_index, i };
|
||||
synth_adjust = prev;
|
||||
synth_adjust.operation = DSGA_OP_RST;
|
||||
synth_adjust.adjust_flags = DSGAF_NONE;
|
||||
found1 = { adjusts.data(), &synth_adjust, i };
|
||||
have_mul = true;
|
||||
}
|
||||
} else if (prev.operation == DSGA_OP_STOP) {
|
||||
@@ -404,12 +392,30 @@ static bool TryMergeBoolMulCombineVarAction2Adjust(VarAction2OptimiseState &stat
|
||||
return;
|
||||
} else if (have_mul) {
|
||||
/* Found second source */
|
||||
found_adjusts[(save_index * 2) + 1] = { adjusts.data(), nullptr, i };
|
||||
found2 = { adjusts.data(), nullptr, i };
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find and replace the result of:
|
||||
* (var * flag) + (var * !flag) with var
|
||||
* (-var * (var < 0)) + (var * !(var < 0)) with abs(var)
|
||||
* "+" may be ADD, OR or XOR.
|
||||
*/
|
||||
static bool TryMergeBoolMulCombineVarAction2Adjust(VarAction2OptimiseState &state, std::vector<DeterministicSpriteGroupAdjust> &adjusts, const int adjust_index)
|
||||
{
|
||||
uint store_var = adjusts[adjust_index].parameter;
|
||||
|
||||
DeterministicSpriteGroupAdjust synth_adjusts[2];
|
||||
VarAction2AdjustDescriptor found_adjusts[4] = {};
|
||||
uint mul_indices[2] = {};
|
||||
|
||||
auto find_adjusts = [&](int start_index, uint save_index) {
|
||||
GetBoolMulSourceAdjusts(adjusts, start_index, store_var, synth_adjusts[save_index], found_adjusts[save_index * 2], found_adjusts[(save_index * 2) + 1], mul_indices + save_index);
|
||||
};
|
||||
|
||||
find_adjusts(adjust_index - 1, 0); // A (first, closest)
|
||||
@@ -1051,6 +1057,41 @@ void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSpecFeatu
|
||||
}
|
||||
switch (adjust.operation) {
|
||||
case DSGA_OP_ADD:
|
||||
if (adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == 0xFFFFFFFF &&
|
||||
(prev_inference & VA2AIF_ONE_OR_ZERO) && (non_const_var_inference & VA2AIF_ONE_OR_ZERO) &&
|
||||
((prev_inference & VA2AIF_MUL_BOOL) || (non_const_var_inference & VA2AIF_MUL_BOOL))) {
|
||||
/* See if this is a ternary operation where both cases result in bool */
|
||||
auto check_ternary_bool = [&]() -> bool {
|
||||
int store_index = GetVarAction2AdjustOfPreviousTempStoreSource(group->adjusts.data(), ((int)group->adjusts.size()) - 2, (adjust.parameter & 0xFF));
|
||||
if (store_index < 0) return false;
|
||||
|
||||
DeterministicSpriteGroupAdjust synth_adjusts[2];
|
||||
VarAction2AdjustDescriptor found_adjusts[4] = {};
|
||||
|
||||
if (prev_inference & VA2AIF_MUL_BOOL) {
|
||||
GetBoolMulSourceAdjusts(group->adjusts, ((int)group->adjusts.size()) - 2, adjust.parameter, synth_adjusts[0], found_adjusts[0], found_adjusts[1], nullptr);
|
||||
} else if (group->adjusts.size() >= 2) {
|
||||
found_adjusts[0] = { group->adjusts.data(), nullptr, ((int)group->adjusts.size()) - 2 };
|
||||
}
|
||||
if (!found_adjusts[0].IsValid() && !found_adjusts[1].IsValid()) return false;
|
||||
|
||||
if (non_const_var_inference & VA2AIF_MUL_BOOL) {
|
||||
GetBoolMulSourceAdjusts(group->adjusts, store_index - 1, adjust.parameter, synth_adjusts[1], found_adjusts[2], found_adjusts[3], nullptr);
|
||||
} else if (store_index >= 1) {
|
||||
found_adjusts[2] = { group->adjusts.data(), nullptr, store_index - 1 };
|
||||
}
|
||||
if (!found_adjusts[2].IsValid() && !found_adjusts[3].IsValid()) return false;
|
||||
|
||||
if (AreVarAction2AdjustsBooleanInverse(found_adjusts[0], found_adjusts[2]) != VA2ABIR_NO) return true;
|
||||
if (AreVarAction2AdjustsBooleanInverse(found_adjusts[0], found_adjusts[3]) != VA2ABIR_NO) return true;
|
||||
if (AreVarAction2AdjustsBooleanInverse(found_adjusts[1], found_adjusts[2]) != VA2ABIR_NO) return true;
|
||||
if (AreVarAction2AdjustsBooleanInverse(found_adjusts[1], found_adjusts[3]) != VA2ABIR_NO) return true;
|
||||
return false;
|
||||
};
|
||||
if (check_ternary_bool()) {
|
||||
state.inference |= VA2AIF_ONE_OR_ZERO | VA2AIF_SIGNED_NON_NEGATIVE;
|
||||
}
|
||||
}
|
||||
try_merge_with_previous();
|
||||
break;
|
||||
case DSGA_OP_SUB:
|
||||
|
Reference in New Issue
Block a user