[Bug middle-end/26724] __builtin_constant_p fails to recognise function with constant return
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26724 Matthijs Kooijman changed: What|Removed |Added CC||matthijs at stdin dot nl --- Comment #5 from Matthijs Kooijman --- I also ran into this problem in an embedded project and the workaround also works for me - thanks! I had already made a short testcase in godbolt for this before I found this report. I'll share it here just in case it is useful for testing this problem later: https://godbolt.org/z/s1eK6a3Pf Here's the code: #include // I added always_inline to see if that would help - seems to make not difference //[[gnu::always_inline]] static inline bool always_true() __attribute__((always_inline)); static inline bool always_true() { return true; } static constexpr inline bool constexpr_always_true() { return true; } int main() { printf("DIRECT: %d\n", __builtin_constant_p(always_true())); bool var = always_true(); printf("VIAVAR: %d\n", __builtin_constant_p(var)); printf("CONSTEXPR: %d\n", __builtin_constant_p(constexpr_always_true())); } Gcc 12.2 outputs: DIRECT: 0 VIAVAR: 1 CONSTEXPR: 1 Two additional observations: - clang seems to behave the same as gcc here - Adding constexpr to the function definition also fixes the problem without the workaround (but might not always be useful - constexpr has more strict requirements than a __builtin_constant_p test). - Adding always_inline attributes makes no difference.
[Bug target/103698] [12 regression] Code assigned to __attribute__((section(".data"))) generates invalid dwarf: leb128 operand is an undefined symbol
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103698 Matthijs Kooijman changed: What|Removed |Added CC||matthijs at stdin dot nl --- Comment #4 from Matthijs Kooijman --- I also ran into this problem, with an STM32 codebase that uses libopencm3 (for peripheral code and the linker script) and uses section(".data") to put a bit of code in RAM (to prevent flash reads while programming flash). To fix this problem in my code, I switched from section(".data") to section(".ramtext"), which is second section that is also put into RAM and seems intended especially for this purpose. This works with the libopencm3 linker script, which defines this section, YMMV with other linker scripts. E.g. from https://github.com/libopencm3/libopencm3/blob/189017b25cebfc609a6c1a5a02047691ef845b1b/ld/linker.ld.S#L136: .data : { _data = .; *(.data*) /* Read-write initialized data */ *(.ramtext*)/* "text" functions to run in ram */ . = ALIGN(4); _edata = .; } >ram AT >rom >From looking at the linker script, it seems that .data and .ramtext are treated pretty much in the same way, so I suspect that there is something else (maybe some builtin rules in gcc/ld/as) that make the data section special in a way that it causes this problem to be triggered. Hopefully this is helpful for anyone else running into this same problem.
[Bug libstdc++/106477] With -fno-exception operator new(nothrow) aborts instead of returning null
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106477 --- Comment #6 from Matthijs Kooijman --- Ah, IIUC your patch does not treat -fno-exceptions specially, but just adds a shortcut for the nothrow new version to skip calling regular new version if it has not been replaced. In a normal build, that saves throw/catch overhead, and in a no-exceptions build that prevents the abort associated with that throw. Clever! One corner case seems to be when the regular new version is replaced in a no-exceptions build, but in that case that replacement has no way to signal failure anyway, and if needed a user can just also replace the nothrow version. I can't comment on the details of the patch wrt aliases and preprocessor stuff, but the approach and the gist of the code looks ok to me.
[Bug libstdc++/68210] nothrow operator fails to call default new
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68210 Matthijs Kooijman changed: What|Removed |Added CC||matthijs at stdin dot nl --- Comment #8 from Matthijs Kooijman --- Note that in comment:2, Jonathan Wakely pointed out a caveat: > Also we certainly don't want to conform to the new requirement when > libstdc++ is built with -fno-exceptions, because allocation failure > would abort in operator new(size_t) and so the nothrow version never > gets a chance to handle the exception and return null. But this was not taken into account when implementing the fix for this issue, meaning nothrow operators are now effectively useless with -fno-exceptions (and there is thus no way to handle allocation failure other than aborting in that case). I created a new bug report about this here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106477
[Bug libstdc++/106477] With -fno-exception operator new(nothrow) aborts instead of returning null
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106477 --- Comment #3 from Matthijs Kooijman --- Created attachment 53384 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53384=edit Testcase - linker script for ATSAMD21G18 (Arduino zero)
[Bug libstdc++/106477] With -fno-exception operator new(nothrow) aborts instead of returning null
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106477 --- Comment #2 from Matthijs Kooijman --- Created attachment 53383 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53383=edit Testcase - startup code
[Bug libstdc++/106477] With -fno-exception operator new(nothrow) aborts instead of returning null
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106477 --- Comment #1 from Matthijs Kooijman --- Created attachment 53382 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53382=edit Testcase - main code
[Bug libstdc++/106477] New: With -fno-exception operator new(nothrow) aborts instead of returning null
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106477 Bug ID: 106477 Summary: With -fno-exception operator new(nothrow) aborts instead of returning null Product: gcc Version: 11.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: matthijs at stdin dot nl Target Milestone: --- The nothrow version of operator new is intended to return null on allocation failure. However, when libstdc++ is compiled with -fno-exceptions, it aborts instead. The cause of this failure is that the nothrow operators work by calling the regular operators, catching any allocation failure exception and turning that into a null return. However, with -fno-exceptions, the regular operator aborts instead of throwing, so the nothrow operator never gets a chance to return null. Originally, this *did* work as expected, because the nothrow operators would just call malloc directly. However, as reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68210 this violates the C++11 requirement that the nothrow versions must call the regular versions (so applications can replace the regular version and get the nothrow for free), so this was changed in https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=b66e5a95c0065fda3569a1bfd3766963a848a00d Note this comment by Jonathan Wakely in the linked report, which actually already warns against introducing the behavior I am describing (but the comment was apparently not considered when applying the fix): https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68210#c2 In any case, we have two conflicting requirements: 1. nothrow operators should return null on failure 2. nothrow operators should call regular operators I can see no way to satisfy both. Since -fno-exceptions is already violating the spec, it would make sense to me to, when -fno-exceptions is specified, only satisfy 1 and allow 2 to be violated (which is more of a fringe case anyway, and applications can always replace the nothrow versions too to get the behavior they need). Essentially this would mean that with -fno-exceptions, the nothrow versions would have to call malloc again directly like before (either duplicating code like before, or maybe introducing a null-returning helper function?). To reproduce, I made a small testcase. I was originally seeing this in the Arduino environment on an Atmel samd chip, but I made a self-contained testcase and tested that using gcc from https://developer.arm.com (using the linker script from Atmel/Arduino), which is compiled with -fno-exceptions. The main testcase is simple: An _sbrk() implementation that always fails to force allocation failure (overriding the default libnosys implementation that always succeeds), and a single call to operator new that should return null, but aborts: $ cat test.cpp #include volatile void* foo; extern "C" void *_sbrk(int n) { // Just always fail allocation return (void*)-1; } int main() { // This should return nullptr, but actually aborts (with -fno-exceptions) foo = new (std::nothrow) char[65000]; return 0; } In addition, I added a minimal startup.c for memory initialization and reset vector and a linker script taken verbatim from https://github.com/arduino/ArduinoCore-samd/raw/master/variants/arduino_zero/linker_scripts/gcc/flash_without_bootloader.ld (I will attach both files next). Compiled using: $ ~/Downloads/gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -g -fno-exceptions --specs=nosys.specs --specs=nano.specs -Tflash_without_bootloader.ld -nostartfiles test.cpp startup.c -lstdc++ Running this on the Arduino zero (using openocd and gdb to upload the code through the EDBG port) shows it aborts: Program received signal SIGINT, Interrupt. _exit (rc=rc@entry=1) at /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/libnosys/_exit.c:16 16 /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/libnosys/_exit.c: No such file or directory. (gdb) bt #0 _exit (rc=rc@entry=1) at /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/libnosys/_exit.c:16 #1 0x013a in abort () at /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/stdlib/abort.c:59 #2 0x0128 in operator new (sz=65000) at /data/jenkins/workspace/GNU-toolchain/arm-11/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54 #3 0x0106 in operator new[] (sz=) at /data/jenkins/workspace/GNU-toolchain/arm-11/src/gcc/libstdc++-v3/libsupc++/new_opv.cc:32 #4 0x00fe in operator new[] (sz=) at /data/jenkins/workspace/GNU-toolchain/arm-11/src/gcc/libstdc++-v3/libsupc++/new_opvnt.cc:38 #5 0x0034 in main () at test.cpp:17
[Bug target/100219] New: Arm/Cortex-M: Suboptimal code returning unaligned struct with non-empty stack frame
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100219 Bug ID: 100219 Summary: Arm/Cortex-M: Suboptimal code returning unaligned struct with non-empty stack frame Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: matthijs at stdin dot nl Target Milestone: --- Consider the program below, which deals with functions returning a struct of two members, either using a literal value or by forwarding the return value from another function. When the struct has no alignment, this results in suboptimal code that breaks the struct (stored in a single registrer) apart into its members and reassembles them into the struct into a single register again, where it could just have done absolutely nothing. Giving the struct some alignment somehow prevents this problem from occuring. Consider this program: $ cat Foo.c struct Result { char a, b; } #if defined(ALIGN) __attribute((aligned(ALIGN)))__ #endif ; struct Result other(const int*); struct Result func1() { int x; return other(); } struct Result func2() { struct Result y = {0x12, 0x34}; return y; } struct Result func3() { return other(0); } Which produces the following code: $ arm-linux-gnueabi-gcc-10 --version arm-linux-gnueabi-gcc-10 (Ubuntu 10.2.0-5ubuntu1~20.04) 10.2.0 $ arm-linux-gnueabi-gcc-10 -fno-stack-protector -mcpu=cortex-m4 -c -O3 ~/Foo.c && objdump -d Foo.o : 0: b500push{lr} 2: b083sub sp, #12 4: a801add r0, sp, #4 6: f7ff fffe bl 0 a: 4603mov r3, r0 c: b2dauxtbr2, r3 e: 2000movsr0, #0 10: f362 0007 bfi r0, r2, #0, #8 14: f3c3 2307 ubfxr3, r3, #8, #8 18: f363 200f bfi r0, r3, #8, #8 1c: b003add sp, #12 1e: f85d fb04 ldr.w pc, [sp], #4 22: bf00nop 0024 : 24: f243 4312 movwr3, #13330 ; 0x3412 28: f003 0212 and.w r2, r3, #18 2c: 2000movsr0, #0 2e: f362 0007 bfi r0, r2, #0, #8 32: 0a1blsrsr3, r3, #8 34: b082sub sp, #8 36: f363 200f bfi r0, r3, #8, #8 3a: b002add sp, #8 3c: 4770bx lr 3e: bf00nop 0040 : 40: b082sub sp, #8 42: 2000movsr0, #0 44: b002add sp, #8 46: f7ff bffe b.w 0 4a: bf00nop Especially note func2, which correctly builds the struct using a single word literal, and then continues to break it apart and rebuild it. Note that I added -fno-stack-protector to make the generated code more consise, but the problem occurs even without this option. Somehow, the alignment influences this, since adding some alignment makes the problem disappear: $ arm-linux-gnueabi-gcc-10 -fno-stack-protector -mcpu=cortex-m4 -c -O3 ~/Foo.c -DALIGN=2 && objdump -d Foo.o Foo.o: file format elf32-littlearm Disassembly of section .text: : 0: b500push{lr} 2: b083sub sp, #12 4: a801add r0, sp, #4 6: f7ff fffe bl 0 a: b003add sp, #12 c: f85d fb04 ldr.w pc, [sp], #4 0010 : 10: f243 4012 movwr0, #13330 ; 0x3412 14: 4770bx lr 16: bf00nop 0018 : 18: 2000movsr0, #0 1a: f7ff bffe b.w 0 1e: bf00nop Other things I've observed: - When using ALIGN=2 or ALIGN=4, the problem disappears as shown above. ALIGN=1 is equivalent to no alignment. Using ALIGN=8 also makes the problem disappear, but it seams this cause the return value to be passed in memory, rather than in r0 directly. - Using -mcpu=arm8, or arm7tdmi, or some other arm cpus I tried, the problem disappears. With all cortex variants I tried the problem stays, though sometimes it seems slightly less severe. - I could not reproduce this on x86_64. - Using a struct with just 1 char, the problem disappears. - Using a struct with 4 chars, the problem stays (and becomes more pronounced because there's more work to rebuild the struct). - Using a struct with 2 shorts, the problem disappears for func2, but stays for func1. - Writing something equivalent in C++, the problem also appears (I originally saw this problem in C++ and then tried reproducing in C). - When
[Bug tree-optimization/97997] Missed optimization: Multiply of extended integer cannot overflow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97997 --- Comment #5 from Matthijs Kooijman --- Awesome, thanks for the quick response and fix!
[Bug tree-optimization/97997] New: Missed optimization: Multiply of extended integer cannot overflow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97997 Bug ID: 97997 Summary: Missed optimization: Multiply of extended integer cannot overflow Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: matthijs at stdin dot nl Target Milestone: --- When an integer is extended and then multiplied by another integer of the original size, the resulting multiplication can never overflow. However, gcc does not seem to realize this. Consider: uint16_t calc_u(uint16_t x ) { return (uint32_t)x * 10 / 10; } If gcc would realize that x * 10 cannot overflow, it can optimize away the * 10 / 10. However, it does not: $ gcc-10 -Os -Wall -Wextra -pedantic foo.c && objdump -S --disassemble=calc_u a.out 11a0 : 11a0: f3 0f 1e fa endbr64 11a4: 0f b7 c7movzwl %di,%eax 11a7: b9 0a 00 00 00 mov$0xa,%ecx 11ac: 31 d2 xor%edx,%edx 11ae: 6b c0 0aimul $0xa,%eax,%eax 11b1: f7 f1 div%ecx 11b3: c3 retq When doing the multiplication signed, this optimization *does* happen: uint16_t calc_s(uint16_t x ) { return (int32_t)x * 10 / 10; } $ gcc-10 -Os -Wall -Wextra -pedantic foo.c && objdump -S --disassemble=calc_s a.out 1199 : 1199: f3 0f 1e fa endbr64 119d: 89 f8 mov%edi,%eax 119f: c3 retq Since signed overflow is undefined, gcc presumably assumes that the multiplication does not overflow and optimizes this. This shows that the machinery for this optimization exists and works and suggests that the only thing missing in the unsigned case is realizing that the overflow cannot happen. The above uses 16/32bit numbers, but the same happens on 32/64bit (just not on 8/16 bit, because then things are integer-promoted and multiplication is always signed). When using -O2 or -O3, the code generated for unsigned is different, but still not fully optimized. Maybe I'm missing some corner case of the C language that would make this optimization incorrect, but I think it should be allowed. The original code that triggered this report is: #define ticks2us(t) (uint32_t)((uint64_t)(t)*100 / TICKS_PER_SEC) Which could be optimized to a single multiply or even bitshift rather than a multiply and division for particular values of TICKS_PER_SEC, while staying generally applicable (but slower) for other values. I took a guess at the component, please correct that if needed. $ gcc-10 --version gcc-10 (Ubuntu 10.2.0-5ubuntu1~20.04) 10.2.0 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.