VarAction2: Infer ternary add result is bool if both branches are bool

This commit is contained in:
Jonathan G Rennison
2022-08-28 11:35:16 +01:00
parent 8c94ba0dc8
commit 2a41854f6b

View File

@@ -350,21 +350,9 @@ static VarAction2AdjustsBooleanInverseResult AreVarAction2AdjustsBooleanInverse(
return VA2ABIR_NO; return VA2ABIR_NO;
} }
/* static void GetBoolMulSourceAdjusts(std::vector<DeterministicSpriteGroupAdjust> &adjusts, int start_index, uint store_var, DeterministicSpriteGroupAdjust &synth_adjust,
* Find and replace the result of: VarAction2AdjustDescriptor &found1, VarAction2AdjustDescriptor &found2, uint *mul_index)
* (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) {
bool have_mul = false; bool have_mul = false;
for (int i = start_index; i >= 0; i--) { for (int i = start_index; i >= 0; i--) {
const DeterministicSpriteGroupAdjust &prev = adjusts[i]; const DeterministicSpriteGroupAdjust &prev = adjusts[i];
@@ -382,21 +370,21 @@ static bool TryMergeBoolMulCombineVarAction2Adjust(VarAction2OptimiseState &stat
} }
} else if (prev.operation == DSGA_OP_MUL && !have_mul) { } 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 */ /* 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) { 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)); int store_index = GetVarAction2AdjustOfPreviousTempStoreSource(adjusts.data(), i - 1, (prev.parameter & 0xFF));
if (store_index >= 1) { if (store_index >= 1) {
/* Found the referenced temp store, use that */ /* 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; have_mul = true;
} }
} }
if (!have_mul) { if (!have_mul) {
/* It's not a temporary storage load which can be followed, synthesise an RST */ /* It's not a temporary storage load which can be followed, synthesise an RST */
synth_adjusts[save_index] = prev; synth_adjust = prev;
synth_adjusts[save_index].operation = DSGA_OP_RST; synth_adjust.operation = DSGA_OP_RST;
synth_adjusts[save_index].adjust_flags = DSGAF_NONE; synth_adjust.adjust_flags = DSGAF_NONE;
found_adjusts[save_index * 2] = { adjusts.data(), synth_adjusts + save_index, i }; found1 = { adjusts.data(), &synth_adjust, i };
have_mul = true; have_mul = true;
} }
} else if (prev.operation == DSGA_OP_STOP) { } else if (prev.operation == DSGA_OP_STOP) {
@@ -404,12 +392,30 @@ static bool TryMergeBoolMulCombineVarAction2Adjust(VarAction2OptimiseState &stat
return; return;
} else if (have_mul) { } else if (have_mul) {
/* Found second source */ /* Found second source */
found_adjusts[(save_index * 2) + 1] = { adjusts.data(), nullptr, i }; found2 = { adjusts.data(), nullptr, i };
return; return;
} else { } else {
return; 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) find_adjusts(adjust_index - 1, 0); // A (first, closest)
@@ -1051,6 +1057,41 @@ void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSpecFeatu
} }
switch (adjust.operation) { switch (adjust.operation) {
case DSGA_OP_ADD: 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(); try_merge_with_previous();
break; break;
case DSGA_OP_SUB: case DSGA_OP_SUB: