cardillan / mindcode

A high level language for Mindustry Logic and Mindustry Schematics.

Home Page:http://mindcode.herokuapp.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Optimization should not replace strictEqual with notEqual

cardillan opened this issue · comments

There's a problem in the ImproveConditionalJumps optimizer: it assumes that notEqual is the opposite operation to strictEqual, but that isn't true: notEqual coerces types, and won't therefore distinguish between null and 0.

It can lead to compiled code that doesn't work as intended. This code snippet:

if @unit.dead === 0
  print("alive")
end

is meant to print "alive" it the @unit variable is not null and its @dead property is equal to 0 (in other words, only if the unit is bound and alive). Optimized code, however, looks like this:

sensor __tmp0 @unit @dead
jump 4 notEqual __tmp0 0
print "alive"
jump 0 always 0 0
end

This will print "alive" even if there's no bound unit (and the @unit variable is therefore null).

I think ImproveConditionalJumps shouldn't modify strictEqual comparisons.

Good point. I'm willing to see and merge a pull request that implements such a fix.

The fix itself would be trivial, but I see other problems with ImproveConditionalJumps:

  • This class seems to predate other optimizers and doesn't use the state-based instruction traversal. I'd say the state-based approach is more readable, and is sort of a standard in other optimizers.
  • The class calls flush() frequently; if there were other optimizers down the line, they might not work (I actually stumbled upon this).
  • Most importantly, the code merges an op comparison instruction with a jump notEqual instruction without verifying - by inspecting the arguments - that the jump operates on the op output or that it really compares it to true. I believe it was based on the knowledge of how the compiler works. Future changes in code generation or other optimizers might cause the assumption to fail, leading to merging instructions that shouldn't be merged.

Would you be able to review a PR if I rewrote the class completely to use the state-based approach and verify the instructions matched the prerequisites for merging? It would be a slightly larger change. I'd separate the rewrite from the fix, so that the unit tests could be run on commit containing just the rewrite.