[Bug middle-end/26724] __builtin_constant_p fails to recognise function with constant return

2023-04-11 Thread matthijs at stdin dot nl via Gcc-bugs
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

2023-04-06 Thread matthijs at stdin dot nl via Gcc-bugs
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

2023-01-15 Thread matthijs at stdin dot nl via Gcc-bugs
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

2022-07-29 Thread matthijs at stdin dot nl via Gcc-bugs
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

2022-07-29 Thread matthijs at stdin dot nl via Gcc-bugs
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

2022-07-29 Thread matthijs at stdin dot nl via Gcc-bugs
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

2022-07-29 Thread matthijs at stdin dot nl via Gcc-bugs
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

2022-07-29 Thread matthijs at stdin dot nl via Gcc-bugs
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

2021-04-22 Thread matthijs at stdin dot nl via Gcc-bugs
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

2020-11-26 Thread matthijs at stdin dot nl via Gcc-bugs
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

2020-11-25 Thread matthijs at stdin dot nl via Gcc-bugs
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.