The option -fisolate-erroneous-paths-dereference in -O2 causes it.
//volatile unsigned int
//unsigned int orgin = *((int *)0); //ok
//unsigned int orgin = *((unsigned int *)0); //ok
unsigned int orgin = *((volatile unsigned int *)0); //nok
arm-none-eabi-gcc --specs=nosys.specs -O2 b.c -o b
arm-none-eabi-gcc --specs=nosys.specs -O1 -fisolate-erroneous-paths-dereference b.c -o b
8210: e3a03000 mov r3, #0
8214: e5933000 ldr r3, [r3]
8218: e7f000f0 udf #0
Why it is "udf #0"?
Is it a BUG?
Please help me, thanks!
I don't know why this would be a bug. You're dereferencin a NULL pointer. udf is an undefined instruction. On x86_64 you'd get the ud2 instruction.
Dereferencing a null pointer is undefined. -fisolate-erroneous-paths-dereference changes some of them into __builtin_trap and for arm that is udf #0.
Thank you for your reply!
"-fisolate-erroneous-paths-dereference" is a new option in GCC-4.9.x.
When I use GCC-4.8.x, it is OK and will not have this problem.
More and more people are switching GCC4.8 to GCC4.9, I think they will meet this problem too. Please help me and tell me how to solve it, thanks.
This code run after DDR init. DDR address range is 0x0 to 0x80000000.
Some operation will get and set the address 0x0.
*((unsigned int *)0) is OK
*((volatile unsigned int *)0) is not OK.
Why the "volatile" makes different?
If I want to use option "-O2" and not contain "-fisolate-erroneous-paths-dereference", how should I configure to compile a cross-toolchain with GCC-4.9.2?
I mean when compile a file with command "gcc -O2 a.c", it will not contain option "-fisolate-erroneous-paths-dereference".
$SRCDIR/$GCC/configure --target=$TARGET \
The problem here is that the code uses undefined behaviour according to the C standard (dereferencing NULL pointer), therefore the compiler is free to do whatever it wants. The user code should be fixed to not do that.
GCC 4.9 is free to change its behaviour from 4.8 in such code because it makes (and shouldn't make) no guarantees about undefined behaviour
(In reply to Airbak from comment #3)
> *((unsigned int *)0) is OK
> *((volatile unsigned int *)0) is not OK.
> Why the "volatile" makes different?
Because volatile prevents the compiler from optimizing that statement out. As stated above, dereferencing a NULL pointer is undefined, so if you do that, all bets are off.
You can use -fno-isolate-erroneous-paths-dereference, but I think the problem is elsewhere.
If dereferencing 0 is ok on your platform, you need at least -fno-delete-null-pointer-checks. I don't know if the isolate pass checks that flag though (it probably should).
Thank you for all reply, it could be closed.