https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94075
Bug ID: 94075 Summary: When using linker-generated list, bad optimization performed in -O2 Product: gcc Version: 5.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: fabrice.girardot at flowbird dot group Target Milestone: --- Created attachment 47992 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47992&action=edit Test case + Makefile to reproduice bug GCC does a wrong optimization in -O2 when using linker-generated lists, when such a list is empty. Linker-generated lists are convenient to automatically group items at link time. A 0-sized item array is located at start of list (section ".foo_1"). A 0-sized item array is located at end of list (section ".foo_3"). All other items with section ".foo_2" will automatically be located between the top and bottom tags. When there is *NO* item with section ".foo_2", the list is empty, the start and end addresses are the same. When compiling with "-O2", gcc assumes start and end addresses can't be equal, and always enter the for() loop in the attached example. If attached example is compiled with "-O0" (please edit Makefile), then generated code is correct. This bug was found on arm-none-eabi-gcc version 6.2.1 with a real linker script for STM32 micro-controller, and the result is an embedded hard fault. For convenient testing under Linux, the Makefile in the attached zip file automatically generates a linker script to add a section for linker-generated lists. ================================== Correct output result (example compiled with -O0): ---------------------------------- $ make clean && make rm -rf output gcc -dumpversion 5.4.0 gcc -c -std=c99 -O0 -DOPTIMIZE="\"-O0\"" -o output/main.o src/main.c ld --verbose \ | sed -n '/===/,$p' \ | sed '/===/d' \ | sed -e '/.rodata[ ]*:/a .foobar : { KEEP(*(SORT(.foo_*))); } ' \ > output/test.ld gcc -Wl,-Map=output/test.map -T output/test.ld -o output/test output/main.o $ output/test I am compiled with '-O0' ! start = 0x4006a0 end = 0x4006a0 ================================== Wrong optimization (example compiled with -O2) ---------------------------------- $ make clean && make rm -rf output gcc -dumpversion 5.4.0 gcc -c -std=c99 -O2 -DOPTIMIZE="\"-O2\"" -o output/main.o src/main.c ld --verbose \ | sed -n '/===/,$p' \ | sed '/===/d' \ | sed -e '/.rodata[ ]*:/a .foobar : { KEEP(*(SORT(.foo_*))); } ' \ > output/test.ld gcc -Wl,-Map=output/test.map -T output/test.ld -o output/test output/main.o $ output/test I am compiled with '-O2' ! start = 0x400680 end = 0x400680 [0] p = 0x400680 ; *p = 0 [1] p = 0x400684 ; *p = 52 [2] p = 0x400688 ; *p = 5 [3] p = 0x40068c ; *p = -736 [4] p = 0x400690 ; *p = 128 [5] p = 0x400694 ; *p = -672 [6] p = 0x400698 ; *p = 168 [7] p = 0x40069c ; *p = -480 [8] p = 0x4006a0 ; *p = 80 [9] p = 0x4006a4 ; *p = -224 Aborting... ==================================