KarolS / KarolS/millfork

Strange invalid 16-bit optimization

Open
#140 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Scala
Stars
279
Forks
21
PR merge metrics
No merged PRs in 30d

Description

I ran across this while working on my Millfork NES game, and initially patched it up with some inline assembly because I wanted to keep going, but it's getting to the point of being annoying. I can try to create a minimal reproducible example if that's necessary, but this is my code:
```
// i'm using addresses for these so my emulator script for drawing a debug overlay knows where to find them
array(word) enemy_xs[12] align(fast) @ $a8
array enemy_ys[12] @ $62
array enemy_types[12] @ $580
array enemy_healths[12] @ $ca
array enemy_data1[12] @ $f1
array enemy_data2[12] @ $6f
array enemy_data3[12] @ $1b
array enemy_tags[12] @ $9d
byte enemy_count @ $9a
// [...]
// part of the code for enemies dying
if (enemy_healths[i] == 0 && enemy_flags[enemy_types[i]] & $20 == 0) {
create_effect($80, enemy_xs[i], enemy_ys[i], $20, 0) // enemy dying from damage
}
destroy_enemy(i)
i += 1
```
On optimization level 1 (which I don't want to use unless I have to), those arguments are compiled into
```
LDA #$80
STA create_effect$type
LDA main$i
ASL
TAY
LDA $A8, Y
INY
STA create_effect$x
LDA $A8, Y
STA create_effect$x + 1
LDY main$i
LDA $62, Y
STA create_effect$y
LDA #$20
STA create_effect$timer
LDA #0
STA create_effect$flags
```
On O2 and up, we instead get
```
LDA main$i
ASL
TAY
LDA $A8, Y
STA create_effect$x + 1
STA create_effect$x
LDY main$i
LDA $62, Y
STA create_effect$y
LDA #$80
```
Some of the arguments are optimized into registers (yay!) but the sketchy thing here is those two `STA` back to back. The low and high bytes of entries of `enemy_xs` are NOT the same. This has shown up in other situations before involving loading from array of words.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the supplied enemy_xs array-of-word case in Millfork and compare generated assembly at optimization levels 1 and 2. Inspect the compiler's 16-bit array-load optimization and verify that the low and high bytes remain distinct in the output, including for a minimal reproducible example.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.