In a little piece of test code, I have the following:
int main(void) { osStatus_t osStat; HAL_Init(); osStat = osKernelInitialize(); if (osStat != osOK) { NVIC_SystemReset(); } while(true); return 0; }
Very simple.
When compiling with -O0, the disassembly for the relevant part looks like:
main: .Lfunc_begin1: .loc 2 31 0 @ ../main.c:31:0 .fnstart .cfi_startproc @ %bb.0: .save {r7, lr} push {r7, lr} .cfi_def_cfa_offset 8 .cfi_offset lr, -4 .cfi_offset r7, -8 .pad #8 sub sp, #8 .cfi_def_cfa_offset 16 movs r0, #0 str r0, [sp, #4] .Ltmp1: .loc 2 34 2 prologue_end @ ../main.c:34:2 bl HAL_Init .loc 2 36 11 @ ../main.c:36:11 bl osKernelInitialize .loc 2 36 9 is_stmt 0 @ ../main.c:36:9 str r0, [sp] .Ltmp2: .loc 2 37 6 is_stmt 1 @ ../main.c:37:6 ldr r0, [sp] .Ltmp3: .loc 2 37 6 is_stmt 0 @ ../main.c:37:6 cbz r0, .LBB1_2 b .LBB1_1 .LBB1_1: .Ltmp4: .loc 2 39 3 is_stmt 1 @ ../main.c:39:3 bl _ZL18__NVIC_SystemResetv
But with -O1 or higher optimization:
main: .Lfunc_begin1: .fnstart .cfi_startproc @ %bb.0: .loc 2 34 2 prologue_end @ ../main.c:34:2 bl HAL_Init .Ltmp1: .loc 2 36 11 @ ../main.c:36:11 bl osKernelInitialize .Ltmp2: @DEBUG_VALUE: main:osStat <- undef .loc 2 39 3 @ ../main.c:39:3 bl _ZL18__NVIC_SystemResetv
All of a sudden, the comparison after the call to osKernelInitialize is gone...The while(true) is only there temporarily, and I am aware that it can be optimized away as it undefined behavior, but I do expect the compiler to actually handle the preceding if-statement properly first.
Interesting, this seems to happen only in C++ mode, and there from C++11 onwards (so not when compiling in C++98), and also only since Arm Compiler 6.17, not with 6.16. Can you confirm this?
Ok, the "issue" is, that since C++11 the while(true); is undefined behavior. So the compiler assumes this outcome of the if statement to while(true); is not possible and the if-statement can only take the other outcome. This makes basically the complete if-statement itself useless and it gets removed as well.One can make this work by adding some statement with possible side-effect in the while loop, like:
while(true);
while (1) __wfe();
Then this code compiles with including the if-statement.
I must say that I really disagree with that the compiler behaves that way with the preceding code that is well behaved because later code is UB.That said, I doubt that it will change, so I accept the answer.