https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128076
Bug ID: 128076
Summary: wrong code at -O2 and -O3 for a tail-recursive
function whose signed additions do not overflow
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: kyuwoncho18 at gmail dot com
Target Milestone: ---
Target: x86_64-pc-linux-gnu
static int f(int n) {
if (n == 0) return 0;
if (n == 1) return f(n - 1) + 2147483647;
return f(n - 1) - 2147483647;
}
int main(void) {
volatile int n = 3;
if (f(n) != -2147483647)
__builtin_abort();
}
godbolt: https://godbolt.org/z/nv8GrsMso
f(1) = 2147483647, f(2) = 0 and f(3) = -2147483647, so no operation overflows.
With -O0, -O1, -O2 -fwrapv or -O2 -fno-optimize-sibling-calls the program exits
normally; with -O2 or -O3 it aborts, on every release from 5.4 to trunk. The
multiplicative variant below (g(1) = g(2) = 1, again without overflow) is
correct up to 15.3 and aborts at -O2 from 16.1 on:
static int g(int n) {
if (n == 0) return 1;
return -2147483646 + 2147483647 * g(n - 1);
}
int main(void) {
if (g(2) != 1)
__builtin_abort();
}