https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350
--- Comment #3 from Andrew Macleod <amacleod at redhat dot com> --- On 3/31/23 03:17, rguenth at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350 > > Richard Biener <rguenth at gcc dot gnu.org> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > CC| |amacleod at redhat dot com > > --- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- > Hmm, the same reproduces with r_imin_imax as ptrdiff_t but the IL is a bit > more obvious: > > <bb 2> [local count: 1073741824]: > _27 ={v} signed_value_source; > _4 = (unsigned long) _27; > _8 = _4 + 2147483648; > if (_8 > 4294967295) > goto <bb 8>; [50.00%] > else > goto <bb 3>; [50.00%] > > <bb 3> [local count: 536870913]: > _30 = _27 + 1; > _28 = (sizetype) _30; > if (_4 <= 4611686018427387900) > goto <bb 4>; [50.00%] > else > goto <bb 5>; [50.00%] > > <bb 5> [local count: 268435458]: > _12 = operator new [] (18446744073709551615); > __builtin_memcpy (_12, &MEM <const char[37]> [(void > *)"0123456789abcdefghijklmnopqrstuvwxyz" + 35B], 2); > sink (_12); > if (_28 <= 4611686018427387900) > goto <bb 9>; [100.00%] > else > goto <bb 7>; [0.00%] > > <bb 9> [local count: 0]: > iftmp.2_37 = _28 * 2; > _39 = operator new [] (iftmp.2_37); > __builtin_memcpy (_39, &MEM <const char[37]> [(void > *)"0123456789abcdefghijklmnopqrstuvwxyz" + 34B], 3); > > so we have (unsigned long)[int_min, int_max] > 4611686018427387900 > && (unsigned long)[int_min+1, int_max+1] <= 4611686018427387900 to > constrain _4. I don't see how we can arrive at [0,0] for iftmp.2_37. Looking at what ranger produces for vrp2 (same code just a few passes later): =========== BB 2 ============ Imports: _28 Exports: _4 _10 _28 _4 : _28(I) _10 : _4 _28(I) Partial equiv (_4 pe64 _28) Relational : (_10 != _4) <bb 2> [local count: 1073741824]: _28 ={v} signed_value_source; _4 = (unsigned long) _28; _10 = _4 + 2147483648; if (_10 > 4294967295) goto <bb 8>; [50.00%] else goto <bb 3>; [50.00%] 2->3 (F) _4 : [irange] unsigned long [0, 2147483647][18446744071562067968, +INF] 2->3 (F) _10 : [irange] unsigned long [0, 4294967295] NONZERO 0xffffffff 2->3 (F) _28 : [irange] long int [-2147483648, 2147483647] on entry top BB3 , _28 has the full range of a signed int in a long int body. =========== BB 3 ============ _4 [irange] unsigned long [0, 2147483647][18446744071562067968, +INF] _28 [irange] long int [-2147483648, 2147483647] Partial equiv (r_imin_imax_8 pe32 _28) Relational : (_31 > r_imin_imax_8) <bb 3> [local count: 536870913]: r_imin_imax_8 = (int) _28; << THIs is varying, which is why it isnt printed anywhere _31 = r_imin_imax_8 + 1; << signed traps on overflowt, so this would be [min+1, +INF] _29 = (sizetype) _31; << sizetype is a larger unsigned object,so the possible values for it are [0, 2147483647][18446744071562067969, +INF] if (_4 <= 4611686018427387900) << this leaves _4 with possible values of [18446744071562067968, +INF] on the FALSE branch. goto <bb 4>; [50.00%] else goto <bb 5>; [50.00%] _29 : [irange] sizetype [0, 2147483647][18446744071562067969, +INF] _31 : [irange] int [-2147483647, +INF] When we recalculate values based on the range of _4 on the false branch, intersected with their knowns ranges, it comes up with this 3->5 (F) _4 : [irange] unsigned long [18446744071562067968, +INF] 3->5 (F) r_imin_imax_8 : [irange] int [-INF, -1] 3->5 (F) _28 : [irange] long int [-2147483648, -1] 3->5 (F) _29 : [irange] sizetype [0, 0][18446744071562067969, +INF] 3->5 (F) _31 : [irange] int [-2147483647, 0] when we feed that value of _4 into [18446744071562067968, +INF] = (unsigned long)28 in BB2, we discover the only possible valiues of _28 are [-2147483648, -1] on this branch. We now go an recalculate r_imin_imax_8, _31 and _29 based on this new value of _28 and come up with those ranges that means when we get to bb5, and see if (_29 <= 4611686018427387900) goto <bb 9>; [100.00%] the only possible value of _29 on this branch is a [0,0] And thats a direct result of _31 = [-INF, -1] + 1 before _20 is created with the cast. yikes. talk about convoluted... > > In fact if I put this into a separate testcase like > > void __attribute__((noipa)) > foo (long signed_value_source) > { > unsigned long temu = signed_value_source; > if (temu + 2147483648 > 4294967295) > ; > else > { > long tems = signed_value_source + 1; > unsigned long temu2 = tems; > if (temu > 4611686018427387900) > if (temu2 <= 4611686018427387900) > { > unsigned long iftmp = temu2 * 2; > if (iftmp == 0) > __builtin_abort (); > } > } > } > > then we optimize this to > > <bb 2> [local count: 1073741824]: > temu_3 = (long unsigned int) signed_value_source_2(D); > _1 = temu_3 + 2147483648; > if (_1 > 4294967295) > goto <bb 5>; [50.00%] > else > goto <bb 3>; [50.00%] > > <bb 3> [local count: 536870913]: > if (signed_value_source_2(D) == -1) > goto <bb 4>; [0.00%] > else > goto <bb 5>; [100.00%] > > <bb 4> [count: 0]: > __builtin_abort (); > > and the outer if doesn't change the inner range result. > I bet if we used temu_3 at the abort point it would. I changed it to bar (temu) from the abort: if (iftmp == 0) bar (temu); From EVRP: temu_5 = (long unsigned int) signed_value_source_4(D); _1 = temu_5 + 2147483648; if (_1 > 4294967295) goto <bb 6>; [INV] else goto <bb 3>; [INV] <bb 3> : tems_7 = signed_value_source_4(D) + 1; temu2_8 = (long unsigned int) tems_7; if (temu_5 > 4611686018427387900) goto <bb 4>; [INV] else goto <bb 6>; [INV] <bb 4> : if (temu2_8 <= 4611686018427387900) goto <bb 5>; [INV] else goto <bb 6>; [INV] <bb 5> : bar (-1); Andrew