On Wed, Oct 01, 2025 at 01:12:38PM +0200, Richard Biener wrote:
> The finite_loop_p query should already do this (if scev_initialized (),
> which it is, for CD-DCE).
It does partially.
I can reproduce e.g. on
-std=c++98 Wstringop-overflow-4.ii -O2 -Wall -Wno-array-bounds
with Jason's patch which prints 4 warnings instead of the expected
two (attached).
finite_loop_p is called on 8 loops during cddce, on the 4 inner ones
it succeeds (despite them not having loop->finite_p set), on the 4 outer
ones it doesn't.
E.g. below is a loop on which it fails.
The recorded value range (alread in dse1 and still after cddce1) is
# RANGE [irange] long int [-1, 0]
_41 = (long int) _1;
In any case, the form of the loop with header containing
# _18 = PHI <_41(19), -1(22)>
if (_18 == 0)
exit
else
latch
doesn't really care what _41 is, even if it would be VARYING, the
loop still has 0 or 1 latch executions, never more.
Perhaps this is too weird case on which nbiter just punts?
loop_4 (header = 23, latch = 22)
{
bb_22 (preds = {bb_21 }, succs = {bb_23 })
{
<bb 22> :
# .MEM_22 = PHI <.MEM_29(21)>
_91 = _17 + 2;
}
bb_23 (preds = {bb_19 bb_22 }, succs = {bb_25 bb_24 })
{
<bb 23> :
# _17 = PHI <_77(19), _91(22)>
# _18 = PHI <_41(19), -1(22)>
# .MEM_30 = PHI <.MEM_76(19), .MEM_22(22)>
if (_18 == 0)
goto <bb 25>; [INV]
else
goto <bb 24>; [INV]
}
bb_25 (preds = {bb_23 }, succs = {bb_21 })
{
<bb 25> :
goto <bb 21>; [100.00%]
}
loop_5 (header = 21, latch = 20
upper_bound 2
likely_upper_bound 2
estimate 2)
{
bb_20 (preds = {bb_21 }, succs = {bb_21 })
{
<bb 20> :
# .MEM_92 = VDEF <.MEM_29>
*_19 ={v} {CLOBBER(bob)};
_93 = _20 + -1;
_94 = _19 + 1;
}
bb_21 (preds = {bb_25 bb_20 }, succs = {bb_20 bb_22 })
{
<bb 21> :
# _19 = PHI <_17(25), _94(20)>
# _20 = PHI <1(25), _93(20)>
# .MEM_29 = PHI <.MEM_30(25), .MEM_92(20)>
if (_20 != -1)
goto <bb 20>; [INV]
else
goto <bb 22>; [INV]
}
}
}
Jakub
static inline unsigned long
unsigned_value (void)
{
extern volatile unsigned long unsigned_value_source;
return unsigned_value_source;
}
static inline unsigned long
unsigned_range (unsigned long min, unsigned long max)
{
unsigned long val = unsigned_value ();
return val < min || max < val ? min : val;
}
void sink (void *);
void
test_strcpy_new_char_array (unsigned long n)
{
unsigned long r = unsigned_range (0, 1);
const char *s1 = ("0123456789abcdefghijklmnopqrstuvwxyz" + sizeof
"0123456789abcdefghijklmnopqrstuvwxyz" - 0 - 1);
char *d1 = (char *) new char[r][1];
__builtin_strcpy (d1, s1);
sink (d1);
const char *s2 = ("0123456789abcdefghijklmnopqrstuvwxyz" + sizeof
"0123456789abcdefghijklmnopqrstuvwxyz" - 1 - 1);
char *d2 = (char *) new char[r][1];
__builtin_strcpy (d2, s2);
sink (d2);
const char *s3 = ("0123456789abcdefghijklmnopqrstuvwxyz" + sizeof
"0123456789abcdefghijklmnopqrstuvwxyz" - 1 - 1);
char *d3 = (char *) new char[r][2];
__builtin_strcpy (d3, s3);
sink (d3);
const char *s4 = ("0123456789abcdefghijklmnopqrstuvwxyz" + sizeof
"0123456789abcdefghijklmnopqrstuvwxyz" - 2 - 1);
char *d4 = (char *) new char[r][2];
__builtin_strcpy (d4, s4);
sink (d4);
}