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.
> 
>

Reply via email to