I've got what to me looks like a relatively simple function, but it ended up a lot longer than I expected when I do the -a assembly output and look through it. There are a lot of calls to l_gint and l_pint - what are these for?
Also, is there a way to make it output source lines in the assembly output so it is easier to follow?
What are calls to l_gint and l_pint for?
Re: What are calls to l_gint and l_pint for?
I use this:
Code: Select all
zcc ... -a --c-code-in-asm --list <file.c>
Code: Select all
...
897 00B1 ;engine/src/memory.c:134: void init_memory(void) {
898 00B1 ; ---------------------------------
899 00B1 ; Function init_memory
900 00B1 ; ---------------------------------
901 00B1 _init_memory:
902 00B1 ;engine/src/memory.c:137: mm_default = &mm_manager_zx128;
903 00B1 21 28 00 ld hl,_mm_manager_zx128
904 00B4 22 00 00 ld (_mm_default),hl
905 00B7 ;engine/src/memory.c:138: zx128_switch_bank( 0 );
906 00B7 2E 00 ld l,0x00
907 00B9 CD 00 00 call _zx128_switch_bank
908 00BC ;engine/src/memory.c:141: heap_init( (unsigned char *) MALLOC_HEAP_ADDRESS, MALLOC_HEAP_SIZE );
909 00BC 21 00 10 ld hl,0x1000
910 00BF E5 push hl
911 00C0 26 BC ld h,0xbc
912 00C2 E5 push hl
913 00C3 CD 00 00 call _heap_init_callee
914 00C6 ;engine/src/memory.c:142: }
915 00C6 C9 ret
...
From the library source, it seems that they are functions used by the peephole optimizer: they seem to do some pretty specific things (e.g. "multiply by 7 the variable pointed to by HL"), but there are much wiser people here that may explain better... :-)
Re: What are calls to l_gint and l_pint for?
Thanks jorgegv, the code in asm and list options are great!
Re: What are calls to l_gint and l_pint for?
The calls are used to optimise the code for size, by replacing the getting and putting of integers values into hl. This doesn't make the code fast. It makes it smaller.
To make it fast use the --opt-code-speed=inlineints option. This is done by default when selecting math16 as it assumes that you will want to move 16bit Float_t (or handled as integers) around quickly and don't mind a bit of overhead.
Also, just a note about using --c-code-in-asm very carefully. It does change the code execution flow substantially. I've spent quite a few nights chasing down phantom issues because of this. For example, it will remove callee and fastcall optimisation to functions that provide it, which also changes the stack management, and this has further bump on effects trying to understand where things are stored and recovered. Useful to understand the general flow of your code in assembly, but for debugging resulting assembly probably best to not use it.
To make it fast use the --opt-code-speed=inlineints option. This is done by default when selecting math16 as it assumes that you will want to move 16bit Float_t (or handled as integers) around quickly and don't mind a bit of overhead.
Also, just a note about using --c-code-in-asm very carefully. It does change the code execution flow substantially. I've spent quite a few nights chasing down phantom issues because of this. For example, it will remove callee and fastcall optimisation to functions that provide it, which also changes the stack management, and this has further bump on effects trying to understand where things are stored and recovered. Useful to understand the general flow of your code in assembly, but for debugging resulting assembly probably best to not use it.
-
- Member
- Posts: 121
- Joined: Mon Mar 26, 2018 1:49 pm
Re: What are calls to l_gint and l_pint for?
Thanks for that comment, I use --c-code-in-asm all the time. I'll switch it to my debug builds only.feilipu wrote: ↑Mon Jul 26, 2021 2:04 am Also, just a note about using --c-code-in-asm very carefully. It does change the code execution flow substantially. I've spent quite a few nights chasing down phantom issues because of this. For example, it will remove callee and fastcall optimisation to functions that provide it, which also changes the stack management, and this has further bump on effects trying to understand where things are stored and recovered. Useful to understand the general flow of your code in assembly, but for debugging resulting assembly probably best to not use it.
Re: What are calls to l_gint and l_pint for?
Should the --opt-code-speed=inlineints be the default? I have a program that the difference is 7709 to 7842 bytes, so it may be somewhat larger, but isn't that worthwhile to avoid all the calls anytime something needs to be done with an int? C is so married to the int.
Re: What are calls to l_gint and l_pint for?
I think the strategy is to fit your program into the often limited space available by making it as small as possible.
And then provide an opportunity to make things faster.
The reverse strategy would potentially leave you with a binary that didn't fit into the space available, blocking further progress.
Also, the "best" option for any code is difficult to quantify without experimentation.
There are quite a few optimisation options available for anyone who wants to find the best compromise.
And then provide an opportunity to make things faster.
The reverse strategy would potentially leave you with a binary that didn't fit into the space available, blocking further progress.
Also, the "best" option for any code is difficult to quantify without experimentation.
There are quite a few optimisation options available for anyone who wants to find the best compromise.
Re: What are calls to l_gint and l_pint for?
As someone who's using z88dk for 10+ years, I can say that size is always more important than speed in C programs (for experienced users).
If I ever needed more speed, I'd write it in (inline or external) Assembly. 90+% of my code would still be in C though.
I'd suggest you to learn assembly if you just want raw speed.
If I ever needed more speed, I'd write it in (inline or external) Assembly. 90+% of my code would still be in C though.
I'd suggest you to learn assembly if you just want raw speed.
Re: What are calls to l_gint and l_pint for?
The assembly to me was just looking very p-code ish with all those calls and when I think of integer handling in C I think it should be something that can be done without calls, but do I see your points.
Re: What are calls to l_gint and l_pint for?
There's also a number of hidden aspects people does not think at when checking a compiler output, the same instructions must be valid in different code structures, just think at how flags differ depending on the instruction and on the datatype ("dec a" versus "dec hl", ld a,0 versus xor a etc..).
Moreover the code to reference variables varies when they are local or global..
Moreover the code to reference variables varies when they are local or global..