2

When optimising, GCC sometimes tells me

assuming signed overflow does not occur when simplifying / or % to >> or &
[-Wstrict-overflow]

I failed to make a reproducible test-case for this, but my production code contains something like

int left = a.left() + (a.width() - b.width()) / 2;

where all the methods return int values.

Why might the compiler's replacement of /2 with >>1 or (e.g.) %4 with &3 lead to integer overflow?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • >> on signed integers is implementation-dependent. See: http://stackoverflow.com/questions/11644362/are-the-results-of-bitwise-operations-on-signed-integers-defined – virgesmith Feb 08 '17 at 10:09
  • I think I misunderstood the warning to mean that the result might be **undefined**. But it's just telling us that it's **implementation-defined**. Which isn't quite so bad - but still useful to be warned about. – Toby Speight Feb 08 '17 at 10:28
  • 1
    Note that this is different to a *programmer* substituting `/` with `>>` for example, as the compiler should know what it's targeting. – Toby Speight Jun 19 '17 at 16:30
  • Does this answer your question? [Arithmetic bit-shift on a signed integer](https://stackoverflow.com/questions/4009885/arithmetic-bit-shift-on-a-signed-integer) – Jay-Pi Dec 30 '21 at 16:53
  • @Jay-Pi: not really, because the compiler should be using an arithmetic (sign-preserving) shift for this optimisation, otherwise it's not equivalent. Perhaps the warning is emitted when arithmetic shift isn't available? – Toby Speight Jan 05 '22 at 10:34

1 Answers1

2

Shifting a new bit into the sign bit causes unexpected results to happen: 1001 (signed decimal: 7) >> 1 results in: 0100 (signed decimal: 4). At least with implementations using two's complement, which is the majority.

Edit: On x86, though, there are shift instructions which preserve the sign bit.

The Techel
  • 918
  • 8
  • 13
  • Last time I checked, binary 1001 was decimal 9, and 9/2==4. Given that the compiler knows that the arguments are (signed) integers, I'd expect it to either (a) use (or emulate) signed right-shift, or (b) skip this simplification if it knows it's unreasonable. – Toby Speight Jun 19 '17 at 16:35
  • This is correct for C and C++17, but does not answer the question: https://stackoverflow.com/a/4009954/9306292 as the language semantics answers the question. For example C++20 has different behavior: https://stackoverflow.com/a/56025569/9306292 – Jay-Pi Dec 30 '21 at 16:55