https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128006
--- Comment #5 from rguenther at suse dot de <rguenther at suse dot de> --- On Thu, 5 Nov 2026, lzy20000419 at outlook dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128006 > > liu zhenyu <lzy20000419 at outlook dot com> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > CC| |lzy20000419 at outlook dot > com > > --- Comment #4 from liu zhenyu <lzy20000419 at outlook dot com> --- > r17-5395 fixes the comment 0 testcase, but three more problems in the same > pow/powi handling of tree-ssa-reassoc.cc are still there on trunk (17.0.0 > 20261105, bd921def14a4). All testcases are UB-free (x = -1 keeps every > intermediate at +-1). Can you open separate bugreports for each of the individual issues plase? > 1) decrement_power wraps for the integer-minimum exponent. The exponent is now > known to be an integer, but `power = real_to_integer (&c) - 1` > (tree-ssa-reassoc.cc:1242) overflows for c = -2^63, and the powi case > (TREE_INT_CST_LOW - 1) does the same for INT_MIN: > > ```c > #include <math.h> > __attribute__((noipa)) double f (double x, double y, double z) > { > return (x * y) * pow (x, -9223372036854775808.0) + z * x; > } > int main (void) > { > if (f (-1.0, 1.0, 0.0) != -1.0) __builtin_abort (); > if (f (-1.0, 1.0, 1.0) != -2.0) __builtin_abort (); > return 0; > } > ``` > > ``` > $ gcc -O2 -fassociative-math -fno-signed-zeros -fno-trapping-math t1.c -lm && > ./a.out > Aborted > ``` > > The reassoc1 dump has `_12 = pow (x_5(D), 9.223372036854775807e+18);`, i.e. > the > exponent went from -2^63 to +2^63-1. -fno-tree-reassoc gives the expected > result. > > 2) attempt_builtin_powi truncates repeat counts. add_repeat_to_ops_vec > (tree-ssa-reassoc.cc:629) stores a HOST_WIDE_INT repeat into > operand_entry::count, which is unsigned int (tree-ssa-reassoc.h:29), so pow > (x, > 2^32) contributes 0 and disappears from the product: > > ```c > #include <math.h> > __attribute__((noipa)) double f (double x, double y) > { > return x * x * x * y * x * x * x * pow (x, 4294967296.0); > } > int main (void) > { > if (f (-1.0, 1.0) != 1.0) __builtin_abort (); > return 0; > } > ``` > > ``` > $ gcc -O2 -ffast-math t2.c -lm && ./a.out > Aborted > ``` > > The generated code has no pow call left. The accumulated count is later > emitted > as an int powi exponent, so sums above INT_MAX wrap as well. > > 3) undistribute_ops_list peels one x per round from a pow/powi with a negative > exponent, so the exponent moves away from 0 and the emitted code is > O(|exponent|): > > ```c > #include <math.h> > double f (double x, double y, double z) > { > return (x * y) * __builtin_powi (x, 8000) + x * z * x * pow (x, -8000.0); > } > ``` > > With `-O2 -fassociative-math -fno-signed-zeros -fno-trapping-math -S`, trunk > emits about 2040 asm lines for this function (290 lines for exponent 1000, > 1040 > for 4000), growing linearly with the exponent. > > Tested: 1) and 2) abort with 14.2.0 and 17.0.0 (20261105); 3) is linear on > both. > > Possible fixes: reject exponents whose decrement is not representable in > stmt_is_power_of_op (or let decrement_power fail), cap acceptable_pow_call > (tree-ssa-reassoc.cc:6109) exponents at INT_MAX and give operand_entry::count > a > wide enough type, and factor a pow/powi with a negative exponent at most once > in undistribute_ops_list. > > Disclaimer: This test case was found with LLM-assisted targeted testing, and > the report was written with LLM assistance. > >
