VarAction2: Replace effective SMAX/SMIN sequences in DSE pass
This commit is contained in:
@@ -5733,10 +5733,22 @@ static bool IsFeatureUsableForDSE(GrfSpecFeature feature)
|
|||||||
return (feature != GSF_STATIONS);
|
return (feature != GSF_STATIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsIdenticalValueLoad(const DeterministicSpriteGroupAdjust *a, const DeterministicSpriteGroupAdjust *b)
|
||||||
|
{
|
||||||
|
if (a == nullptr && b == nullptr) return true;
|
||||||
|
if (a == nullptr || b == nullptr) return false;
|
||||||
|
|
||||||
|
if (a->variable == 0x7B || a->variable == 0x7E) return false;
|
||||||
|
|
||||||
|
return std::tie(a->type, a->variable, a->shift_num, a->parameter, a->and_mask, a->add_val, a->divmod_val) ==
|
||||||
|
std::tie(b->type, b->variable, b->shift_num, b->parameter, b->and_mask, b->add_val, b->divmod_val);
|
||||||
|
}
|
||||||
|
|
||||||
static const DeterministicSpriteGroupAdjust *GetVarAction2PreviousSingleLoadAdjust(const std::vector<DeterministicSpriteGroupAdjust> &adjusts, int start_index, bool *is_inverted)
|
static const DeterministicSpriteGroupAdjust *GetVarAction2PreviousSingleLoadAdjust(const std::vector<DeterministicSpriteGroupAdjust> &adjusts, int start_index, bool *is_inverted)
|
||||||
{
|
{
|
||||||
bool passed_store_perm = false;
|
bool passed_store_perm = false;
|
||||||
if (is_inverted != nullptr) *is_inverted = false;
|
if (is_inverted != nullptr) *is_inverted = false;
|
||||||
|
std::bitset<256> seen_stores;
|
||||||
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];
|
||||||
if (prev.variable == 0x7E) {
|
if (prev.variable == 0x7E) {
|
||||||
@@ -5752,10 +5764,15 @@ 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 */
|
/* 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (prev.variable == 0x7D && prev.parameter < 0x100 && seen_stores[prev.parameter]) {
|
||||||
|
/* If we passed a store then a load from that same store is not valid */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return &prev;
|
return &prev;
|
||||||
} else if (prev.operation == DSGA_OP_STO) {
|
} else if (prev.operation == DSGA_OP_STO) {
|
||||||
if (prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask < 0x100) {
|
if (prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask < 0x100) {
|
||||||
/* Temp store */
|
/* Temp store */
|
||||||
|
seen_stores.set(prev.and_mask, true);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
/* Special register store or unpredictable store, don't try to optimise following load */
|
/* Special register store or unpredictable store, don't try to optimise following load */
|
||||||
@@ -7042,19 +7059,41 @@ static std::bitset<256> HandleVarAction2DeadStoreElimination(DeterministicSprite
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (i >= 0 && i + 1 < (int)group->adjusts.size()) {
|
} else {
|
||||||
/* See if having removed the store, there is now a useful pair of operations which can be combined */
|
while (i >= 0 && i + 1 < (int)group->adjusts.size()) {
|
||||||
DeterministicSpriteGroupAdjust &prev = group->adjusts[i];
|
/* See if having removed the store, there is now a useful pair of operations which can be combined */
|
||||||
DeterministicSpriteGroupAdjust &next = group->adjusts[i + 1];
|
DeterministicSpriteGroupAdjust &prev = group->adjusts[i];
|
||||||
if (next.type == DSGA_TYPE_NONE && next.operation == DSGA_OP_XOR && next.variable == 0x1A && next.shift_num == 0 && next.and_mask == 1) {
|
DeterministicSpriteGroupAdjust &next = group->adjusts[i + 1];
|
||||||
/* XOR: boolean invert */
|
if (next.type == DSGA_TYPE_NONE && next.operation == DSGA_OP_XOR && next.variable == 0x1A && next.shift_num == 0 && next.and_mask == 1) {
|
||||||
if (IsEvalAdjustOperationRelationalComparison(prev.operation)) {
|
/* XOR: boolean invert */
|
||||||
prev.operation = InvertEvalAdjustRelationalComparisonOperation(prev.operation);
|
if (IsEvalAdjustOperationRelationalComparison(prev.operation)) {
|
||||||
erase_adjust(i + 1);
|
prev.operation = InvertEvalAdjustRelationalComparisonOperation(prev.operation);
|
||||||
} else if (prev.operation == DSGA_OP_RST && IsConstantComparisonAdjustType(prev.type)) {
|
erase_adjust(i + 1);
|
||||||
prev.type = InvertConstantComparisonAdjustType(prev.type);
|
continue;
|
||||||
erase_adjust(i + 1);
|
} else if (prev.operation == DSGA_OP_RST && IsConstantComparisonAdjustType(prev.type)) {
|
||||||
|
prev.type = InvertConstantComparisonAdjustType(prev.type);
|
||||||
|
erase_adjust(i + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (i >= 1 && prev.type == DSGA_TYPE_NONE && IsEvalAdjustOperationRelationalComparison(prev.operation) &&
|
||||||
|
prev.variable == 0x1A && prev.shift_num == 0 && next.operation == DSGA_OP_MUL) {
|
||||||
|
if (((prev.operation == DSGA_OP_SGT && (prev.and_mask == 0 || prev.and_mask == (uint)-1)) || (prev.operation == DSGA_OP_SGE && (prev.and_mask == 0 || prev.and_mask == 1))) &&
|
||||||
|
IsIdenticalValueLoad(GetVarAction2PreviousSingleLoadAdjust(group->adjusts, i - 1, nullptr), &next)) {
|
||||||
|
prev.operation = DSGA_OP_SMAX;
|
||||||
|
prev.and_mask = 0;
|
||||||
|
erase_adjust(i + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (((prev.operation == DSGA_OP_SLE && (prev.and_mask == 0 || prev.and_mask == (uint)-1)) || (prev.operation == DSGA_OP_SLT && (prev.and_mask == 0 || prev.and_mask == 1))) &&
|
||||||
|
IsIdenticalValueLoad(GetVarAction2PreviousSingleLoadAdjust(group->adjusts, i - 1, nullptr), &next)) {
|
||||||
|
prev.operation = DSGA_OP_SMIN;
|
||||||
|
prev.and_mask = 0;
|
||||||
|
erase_adjust(i + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pending_restart) restart();
|
if (pending_restart) restart();
|
||||||
|
Reference in New Issue
Block a user