The workaround, until the fix, is to introduce a temporary:

    maths_point_u8 t = { position->x * 2, position->y * 2 };
    *screen = t;

The generated inline code looks good then:

;t.c:29: PositionToTile( &position, &screen );
;t.c:10: maths_point_u8 t = { position->x * 2, position->y * 2 };
    ld  a, -8 (ix)
    add a, a
    ld  -2 (ix), a
    ld  a, -6 (ix)
    add a, a
    ld  -1 (ix), a

Edit: Taking a look again, the code is actually not as efficient as it could be. The full expansion of both lines is:

;3862.c:11: maths_point_u8 t =  { position->x * 2, position->y * 2 };
    ld  a, -8 (ix)
    add a, a
    ld  -2 (ix), a
    ld  a, -6 (ix)
    add a, a
    ld  -1 (ix), a
;3862.c:12: *screen = t;
    ld  hl, #4
    add hl, sp
    ex  de, hl
    ld  hl, #6
    add hl, sp
    ldi
    ld  a, (hl)
    ld  (de), a

where the whole second part is all for just the two bytes, the address of which could have been known immediately and also accessible via IX in this case. So the most effective way to write PositionToTile (and also a workaround) is still just:

    screen->x = position->x * 2;
    screen->y = position->y * 2;

which, when inlined, produces much less code:

;3862.c:33: PositionToTile( &position, &screen );
;3862.c:13: screen->x = position->x * 2;
    ld  a, -6 (ix)
    add a, a
    ld  -2 (ix), a
;3862.c:14: screen->y = position->y * 2;
    ld  a, -4 (ix)
    add a, a
    ld  -1 (ix), a
;3862.c:36: printf( "End\n" );    

and, of course, even better code is generated if the position and screen are global:

;3862.c:13: screen->x = position->x * 2;
    ld  a, (#_position + 0)
    add a, a
    ld  hl, #_screen
    ld  (hl), a
;3862.c:14: screen->y = position->y * 2;
    inc hl
    ld  a, (#_position + 2)
    add a, a
    ld  (hl), a
;3862.c:36: printf( "End\n" );
 

Last edit: Janko Stamenović 2025-07-30