From 3b5eede3fc9308b7c7c065e01c81f36fb6814fc1 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 25 May 2022 20:04:36 +0100 Subject: [PATCH] VarAction2: Detect and replace operations which always produce 0 --- src/newgrf.cpp | 21 +++++++++++++++++++++ src/newgrf_spritegroup.h | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 0d569e0acf..b442b9ab95 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5677,6 +5677,27 @@ static void NewSpriteGroup(ByteReader *buf) /* Delete useless zero operations */ group->adjusts.pop_back(); inference = prev_inference; + } else if (adjust.and_mask == 0 && IsEvalAdjustWithZeroAlwaysZero(adjust.operation)) { + /* Operation always returns 0, replace it and any useless prior operations */ + group->adjusts.pop_back(); + while (!group->adjusts.empty()) { + const DeterministicSpriteGroupAdjust &prev = group->adjusts.back(); + if (prev.variable != 0x7E && !IsEvalAdjustWithSideEffects(prev.operation)) { + /* Delete useless operation */ + group->adjusts.pop_back(); + } else { + break; + } + } + DeterministicSpriteGroupAdjust &replacement = group->adjusts.emplace_back(); + replacement.operation = group->adjusts.size() == 1 ? DSGA_OP_ADD : DSGA_OP_RST; + replacement.variable = 0x1A; + replacement.shift_num = 0; + replacement.type = DSGA_TYPE_NONE; + replacement.and_mask = 0; + replacement.add_val = 0; + replacement.divmod_val = 0; + inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO | VA2AIF_PREV_MASK_ADJUST; } else { switch (adjust.operation) { case DSGA_OP_SMIN: diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 2bfbf29b42..316157af7c 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -186,6 +186,32 @@ inline bool IsEvalAdjustWithZeroRemovable(DeterministicSpriteGroupAdjustOperatio } } +inline bool IsEvalAdjustWithZeroAlwaysZero(DeterministicSpriteGroupAdjustOperation op) +{ + switch (op) { + case DSGA_OP_UMIN: + case DSGA_OP_MUL: + case DSGA_OP_AND: + case DSGA_OP_RST: + return true; + + default: + return false; + } +} + +inline bool IsEvalAdjustWithSideEffects(DeterministicSpriteGroupAdjustOperation op) +{ + switch (op) { + case DSGA_OP_STO: + case DSGA_OP_STOP: + return true; + + default: + return false; + } +} + inline bool IsEvalAdjustUsableForConstantPropagation(DeterministicSpriteGroupAdjustOperation op) { switch (op) {