The main gist of the issue was due to changes in the MSX library - basically more of it was being linked in - in particular stdio was coming in. The below is a copy of my email to Rogerup showing the investigation approach.
Running with -z80-verb (for the old version) and -Cl-v -Ca-v for the new version there's some interesting logging:
New:
Module 'psmsx_c' size: 3166 bytes
Module 'msx_crt0' size: 187 bytes
Linking library module 'fputc_cons'
Linking library module 'closeall_c'
Linking library module 'fabandon'
Linking library module 'fclose_c'
Linking library module 'close'
Linking library module 'l_and'
Linking library module 'l_div'
Linking library module 'l_eq'
Linking library module 'l_gchar'
Linking library module 'l_ge'
Linking library module 'l_compare_result'
Linking library module 'l_gint'
Linking library module 'l_gintspsp'
Linking library module 'l_g2intspsp'
Linking library module 'l_gt'
Linking library module 'l_jphl'
Linking library module 'l_le'
Linking library module 'l_mul'
Linking library module 'l_ne'
Linking library module 'l_pint'
Linking library module 'l_uge'
Linking library module 'l_divs_16_16x16'
Linking library module 'l_small_divs_16_16x16'
Linking library module 'l_neg_de'
Linking library module 'l_neg_hl'
Linking library module 'error_divide_by_zero_mc'
Linking library module 'error_edom_mc'
Linking library module 'errno_mc'
Linking library module '_errno'
Linking library module 'error_mc'
Linking library module 'l_small_divu_16_16x16'
Linking library module 'l_mulu_16_16x16'
Linking library module 'l_small_mul_16_16x16'
Total size: 3853
Old:
(psmsx) Size of module is 3262 bytes
(msx_crt0) Size of module is 71 bytes
Linking library module <L_AND>
Linking library module <L_DIV>
Linking library module <L_DIV_U>
Linking library module <L_EQ>
Linking library module <L_GCHAR>
Linking library module <L_GE>
Linking library module <L_GINT>
Linking library module <L_GT>
Linking library module <L_LE>
Linking library module <L_LT>
Linking library module <L_MULT>
Linking library module <L_NE>
Linking library module <L_PINT>
Linking library module <L_SXT>
Linking library module <L_UGE>
Linking library module <L_UGT>
Linking library module <L_ULE>
Linking library module <L_ULT>
Total size: 3556
So from that we can see that the compiled code is smaller, so it must be in the library modules that are being linked.
For the new compiler, we can see that some of stdio is being dragged in, you're bypassing it so we can disabled it with: -pragma-define:CRT_ENABLE_STDIO=0:
zcc +msx psmsx.c -o a -compiler=sccz80 -lndos -pragma-define:CRT_ENABLE_STDIO=0 -Cl-v -Ca-v
Module 'msx_crt0' size: 69 bytes
And a total size of 3586. Looking at the linked library modules we still have this:
Linking library module 'fputc_cons'
Which again you're not using. So why is it being pulled in? This is related to
https://github.com/z88dk/z88dk/issues/692 - because it ends up being defined in the crt0 it ends up being linked in. We can however override the definition and point it to something else that's being used, so lets point it to the main function:
zcc +msx psmsx.c -o a -compiler=sccz80 -lndos -pragma-define:CRT_ENABLE_STDIO=0 -Cl-v -Ca-v -pragma-redirect:fputc_cons=_main
Total code size 3552
Going further, lets assume that all chars are unsigned:
zcc +msx psmsx.c -o a -compiler=sccz80 -lndos -pragma-define:CRT_ENABLE_STDIO=0 -Cl-v -Ca-v -pragma-redirect:fputc_cons=_main -Cc-unsigned
Total code size 3425
Let's try something a bit odd, inlining as much as we can (see
https://github.com/z88dk/z88dk/wiki/WritingOptimalCode)
zcc +msx psmsx.c -o a -compiler=sccz80 -lndos -pragma-define:CRT_ENABLE_STDIO=0 -Cl-v -Ca-v -pragma-redirect:fputc_cons=_main -O2 -Cc-unsigned --opt-code-speed=all
Total code size 3420
I have to admit that last one isn't the result I was expecting. I'm guessing that if the routine is only used once, it ends up using less memory to inline the specific case rather than link to the generalised library routine.