Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

unoptimized behaviour of arm compiler

In my source code I saw a weird behavior of arm compiler where it did redundant iteration over a string, which unnecessary. I display here a minimal example that shows that,and ask my question below that

#include <string.h>
#define MIN(x, y) (((x) < (y)) ? (x) : (y))

int MAX_FILE_NAME = 2500;
int F(char *file){
    int file_len = MIN(strlen(file), MAX_FILE_NAME - 1);
    return file_len;
}
int main(void) {
    F(__FILE__);
    return 0 ;
}

compiled with:

arm-none-eabi-gcc -nostdlib -Xlinker -Map="m7_experiments.map" -Xlinker --cref -Xlinker --gc-sections -Xlinker -print-memory-usage -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -T "m7_experiments_Debug.ld" -o "m7_experiments.axf"  ./src/cr_startup_cm7.o ./src/crp.o ./src/flashconfig.o ./src/m7_experiments.o   

Leads to:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Dump of assembler code for function F:
   0x00000104 <+0>:     push    {r4, lr}
   0x00000106 <+2>:     mov     r4, r0
   0x00000108 <+4>:     bl      0x13c <strlen>
   0x0000010c <+8>:     mov     r2, r0
   0x0000010e <+10>:    ldr     r3, [pc, #20]   ; (0x124 <F+32>)
   0x00000110 <+12>:    ldr     r0, [r3, #0]
   0x00000112 <+14>:    subs    r0, #1
   0x00000114 <+16>:    cmp     r2, r0
   0x00000116 <+18>:    bcc.n   0x11a <F+22>
   0x00000118 <+20>:    pop     {r4, pc}
   0x0000011a <+22>:    mov     r0, r4
   0x0000011c <+24>:    bl      0x13c <strlen>
   0x00000120 <+28>:    b.n     0x118 <F+20>
   0x00000122 <+30>:    nop
   0x00000124 <+32>:    lsls    r0, r3, #6
   0x00000126 <+34>:    movs    r0, r0

Note how in the case that the file length is shorter than the defined one, instead of just getting it’s length from $r2 it’s being computed again, worsening the time run to be as long as 2* file length. which seems unnecessary. Is there some way to justify the compiler behavior in this case? I’m interested to know.

>Solution :

It is redundant. But that is because of your code, not the compiler. That macro is going to expand to this:

// x = strlen(file)
// y = MAX_FILE_NAME - 1
(((strlen(file)) < (MAX_FILE_NAME - 1)) ? (strlen(file)) : (MAX_FILE_NAME - 1))

Remember, the preprocessor is essentially just a glorified copy and paste machine. You’re calling strlen twice. Try this:

int file_len = strlen(file);
file_len = MIN(file_len, MAX_FILE_NAME - 1);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading