public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "earlephilhower at yahoo dot com" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/114421] New: arm-none-eabi thumb -Os (and -O2) incorrectly optimizes out needed class member call
Date: Thu, 21 Mar 2024 19:37:59 +0000	[thread overview]
Message-ID: <bug-114421-4@http.gcc.gnu.org/bugzilla/> (raw)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114421

            Bug ID: 114421
           Summary: arm-none-eabi thumb -Os (and -O2) incorrectly
                    optimizes out needed class member call
           Product: gcc
           Version: 12.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: earlephilhower at yahoo dot com
  Target Milestone: ---

Created attachment 57760
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57760&action=edit
sample.ii output of save-temps

Running g++ 12.3.0 cross-compiling to arm-none-eabi for
armv6s-m/thumb/cortex-m0plus.

When the following small C++ code is compiled using no optimization options,
the call to the C++ class's isEmpty is properly generated (and returns true
forever since head and tail are only ever assigned in the constructor and
they're both 0) and an infinite loop happens (as expected).  When using -Os or
-O2, g++ completely drops the call to the isEmpty member and the while() loop
(which should be infinite) isn't there and main() devolves into a simple set of
printfs.

-- sample.cpp
#include <stdio.h>
#include <stdint.h>

class SimpleFIFO {
public:
  SimpleFIFO() { head = 0; tail = 0; }

public:
  bool isEmpty() { return( head == tail ); }

  uint16_t head;
  uint16_t tail;
};

static SimpleFIFO fifo;

int main(int argc, char **argv) {
  (void) argc;
  (void) argv;

  printf("isEmpty = %d\n", fifo.isEmpty() );

  while( fifo.isEmpty() ); // -> while( true ) !!!

  // should *never* come here
  printf( "NO WAY ! ! !");
}
---


Failing compilation G++ -v output (save-temps .i attached)
---
$ ../system/arm-none-eabi/bin/arm-none-eabi-g++ -v -save-temps -Os -Wall
-Wextra -c sample.cpp 
Using built-in specs.
COLLECT_GCC=../system/arm-none-eabi/bin/arm-none-eabi-g++
Target: arm-none-eabi
Configured with: /workdir/repo/gcc-gnu/configure
--prefix=/workdir/arm-none-eabi.x86_64 --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=arm-none-eabi --disable-shared --with-newlib
--enable-threads=no --disable-__cxa_atexit --disable-libgomp
--disable-libmudflap --disable-nls --without-python --disable-bootstrap
--enable-languages=c,c++ --disable-lto --enable-static=yes
--disable-libstdcxx-verbose --disable-decimal-float --with-cpu=cortex-m0plus
--with-no-thumb-interwork
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 12.3.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Os' '-Wall' '-Wextra' '-c'
'-mcpu=cortex-m0plus' '-mthumb' '-mlibarch=armv6s-m' '-march=armv6s-m'

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../libexec/gcc/arm-none-eabi/12.3.0/cc1plus
-E -quiet -v -imultilib thumb -iprefix
/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/
-D__USES_INITFINI__ sample.cpp -mcpu=cortex-m0plus -mthumb -mlibarch=armv6s-m
-march=armv6s-m -Wall -Wextra -Os -fpch-preprocess -o sample.ii
ignoring nonexistent directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/sys-include"
ignoring duplicate directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include/c++/12.3.0"
ignoring duplicate directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include/c++/12.3.0/arm-none-eabi/thumb"
ignoring duplicate directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include/c++/12.3.0/backward"
ignoring duplicate directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/12.3.0/include"
ignoring duplicate directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/12.3.0/include-fixed"
ignoring nonexistent directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/sys-include"
ignoring duplicate directory
"/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/../../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include"
#include "..." search starts here:
#include <...> search starts here:

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include/c++/12.3.0

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include/c++/12.3.0/arm-none-eabi/thumb

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include/c++/12.3.0/backward

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/include

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/include-fixed

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Os' '-Wall' '-Wextra' '-c'
'-mcpu=cortex-m0plus' '-mthumb' '-mlibarch=armv6s-m' '-march=armv6s-m'

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../libexec/gcc/arm-none-eabi/12.3.0/cc1plus
-fpreprocessed sample.ii -quiet -dumpbase sample.cpp -dumpbase-ext .cpp
-mcpu=cortex-m0plus -mthumb -mlibarch=armv6s-m -march=armv6s-m -Os -Wall
-Wextra -version -o sample.s
GNU C++17 (GCC) version 12.3.0 (arm-none-eabi)
        compiled by GNU C version 7.5.0, GMP version 6.1.2, MPFR version 3.1.4,
MPC version 1.0.3, isl version isl-0.18-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++17 (GCC) version 12.3.0 (arm-none-eabi)
        compiled by GNU C version 7.5.0, GMP version 6.1.2, MPFR version 3.1.4,
MPC version 1.0.3, isl version isl-0.18-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: dc9eae539d88e5656ba12943b9054a3c
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Os' '-Wall' '-Wextra' '-c'
'-mcpu=cortex-m0plus' '-mthumb' '-mlibarch=armv6s-m' '-march=armv6s-m'

/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/as
-march=armv6s-m -meabi=5 -o sample.o sample.s
COMPILER_PATH=/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../libexec/gcc/arm-none-eabi/12.3.0/:/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../libexec/gcc/:/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/
LIBRARY_PATH=/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/thumb/:/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/lib/thumb/:/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/:/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/:/home/earle/Arduino/hardware/pico/rp2040/system/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/lib/
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Os' '-Wall' '-Wextra' '-c'
'-mcpu=cortex-m0plus' '-mthumb' '-mlibarch=armv6s-m' '-march=armv6s-m'
---


When built using the command line "arm-none-eabi-g++ -v -save-temps -Os -Wall
-Wextra -c sample.cpp", main disassembles per objdump to just a couple
printf()s:
---
00000000 <main>:
   0:   b510            push    {r4, lr}
   2:   4b07            ldr     r3, [pc, #28]   @ (20 <main+0x20>)
   4:   4807            ldr     r0, [pc, #28]   @ (24 <main+0x24>)
   6:   8859            ldrh    r1, [r3, #2]
   8:   881b            ldrh    r3, [r3, #0]
   a:   1ac9            subs    r1, r1, r3
   c:   424b            negs    r3, r1
   e:   4159            adcs    r1, r3
  10:   f7ff fffe       bl      0 <printf>
  14:   4804            ldr     r0, [pc, #16]   @ (28 <main+0x28>)
  16:   f7ff fffe       bl      0 <printf>
  1a:   2000            movs    r0, #0
  1c:   bd10            pop     {r4, pc}
  1e:   46c0            nop                     @ (mov r8, r8)
        ...
  28:   0000000e        .word   0x0000000e
---

But, without any optimization options
("../system/arm-none-eabi/bin/arm-none-eabi-g++ -v -save-temps -Wall -Wextra -c
sample.cpp") we do see the call to the class function isEmpty (essentially
making the while() an infinite loop in this trivial example)

---
00000000 <main>:
   0:   b580            push    {r7, lr}
   2:   b082            sub     sp, #8
   4:   af00            add     r7, sp, #0
   6:   6078            str     r0, [r7, #4]
   8:   6039            str     r1, [r7, #0]
   a:   4b0d            ldr     r3, [pc, #52]   @ (40 <main+0x40>)
   c:   0018            movs    r0, r3
   e:   f7ff fffe       bl      0 <main>
  12:   0003            movs    r3, r0
  14:   001a            movs    r2, r3
  16:   4b0b            ldr     r3, [pc, #44]   @ (44 <main+0x44>)
  18:   0011            movs    r1, r2
  1a:   0018            movs    r0, r3
  1c:   f7ff fffe       bl      0 <printf>
  20:   46c0            nop                     @ (mov r8, r8)
  22:   4b07            ldr     r3, [pc, #28]   @ (40 <main+0x40>)
  24:   0018            movs    r0, r3
  26:   f7ff fffe       bl      0 <main>
  2a:   1e03            subs    r3, r0, #0
  2c:   d1f9            bne.n   22 <main+0x22>
  2e:   4b06            ldr     r3, [pc, #24]   @ (48 <main+0x48>)
  30:   0018            movs    r0, r3
  32:   f7ff fffe       bl      0 <printf>
  36:   2300            movs    r3, #0
  38:   0018            movs    r0, r3
  3a:   46bd            mov     sp, r7
  3c:   b002            add     sp, #8
  3e:   bd80            pop     {r7, pc}
        ...
  48:   00000010        .word   0x00000010
---

Originally spotted by another user and documented here:
https://github.com/earlephilhower/arduino-pico/discussions/2062

Apologies in advance if this is a generic C++ undefined behavior, but I can't
see anything and when run natively on the x86_64 (and -m32 x86) all
optimization levels get the expected infinite loop and valgrind shows no
warnings.

Thanks for any assistance,
-EFP3

             reply	other threads:[~2024-03-21 19:38 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-21 19:37 earlephilhower at yahoo dot com [this message]
2024-03-21 19:43 ` [Bug c++/114421] " pinskia at gcc dot gnu.org
2024-03-21 19:53 ` earlephilhower at yahoo dot com
2024-03-21 20:01 ` xry111 at gcc dot gnu.org
2024-03-21 21:40 ` pinskia at gcc dot gnu.org
2024-03-21 21:46 ` pinskia at gcc dot gnu.org
2024-03-21 21:47 ` pinskia at gcc dot gnu.org
2024-03-21 21:48 ` pinskia at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-114421-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).