1 #include <stdio.h>
2 #include <stdbool.h>
3
4 bool flag;
5
6 static void foo(int a, int b)
7 {
8 printf("why\n");
9 return;
10 }
11
12 int main()
13 {
14
15 while (!flag) {
16 foo(10, 11);
17 }
18
19 return 0;
20 }
build with aarch64-linux-gnu-gcc -O2 t.c
objdump with aarch64-linux-gnu-objdump -Sdf a.out > t
55 0000000000400460 <main>:
56 400460: a9be7bfd stp x29, x30, [sp, #-32]!
57 400464: 910003fd mov x29, sp
58 400468: f9000bf3 str x19, [sp, #16]
59 40046c: b0000093 adrp x19, 411000 <__libc_start_main@GLIBC_2.17>
60 400470: 3940c660 ldrb w0, [x19, #49]
61 400474: 35000140 cbnz w0, 40049c <main 0x3c>
62 400478: f9000fb4 str x20, [x29, #24]
63 40047c: 9100c673 add x19, x19, #0x31
64 400480: 90000014 adrp x20, 400000 <_init-0x3e8>
65 400484: 91198294 add x20, x20, #0x660
66 400488: aa1403e0 mov x0, x20
67 40048c: 97fffff1 bl 400450 <puts@plt>
68 400490: 39400260 ldrb w0, [x19]
69 400494: 34ffffa0 cbz w0, 400488 <main 0x28>
70 400498: f9400fb4 ldr x20, [x29, #24]
71 40049c: 52800000 mov w0, #0x0 // #0
72 4004a0: f9400bf3 ldr x19, [sp, #16]
73 4004a4: a8c27bfd ldp x29, x30, [sp], #32
74 4004a8: d65f03c0 ret
my concern is why #68 always load flag from memory? it's not a volatile type, isn't it only load from mem one time then read from register? if I remove c code #16, there's no function call in loop, I can see it load flag from memory only one time.
it seems function call in loop do the magic.
any explanation on this?
CodePudding user response:
Because flag
has external linkage and the compiler cannot assume that it won't get updated from another translation unit in the middle of execution.
Change flag
to static
or make it local and then the whole program will be replaced with an eternal loop calling puts
over and over.
Edit: relevant disassembly from gcc 12.1 for ARM64 -O3
of the original code:
.L3:
mov x0, x20
bl puts
ldrb w0, [x19]
cbz w0, .L3
Changing flag
to static
creates an eternal loop:
.L2:
mov x0, x19
bl puts
b .L2
Keeping flag
as extern linkage but commenting out the function call:
.L3:
b .L3
The last one happens since the loop body no longer contains no side effects such as printing, if the function call is removed. It is then pointless to check the variable.