PR78153
Richard Biener
rguenther@suse.de
Mon Nov 21 09:40:00 GMT 2016
On Sun, 20 Nov 2016, Prathamesh Kulkarni wrote:
> Hi,
> As suggested by Martin in PR78153 strlen's return value cannot exceed
> PTRDIFF_MAX.
> So I set it's range to [0, PTRDIFF_MAX - 1] in extract_range_basic()
> in the attached patch.
>
> However it regressed strlenopt-3.c:
>
> Consider fn1() from strlenopt-3.c:
>
> __attribute__((noinline, noclone)) size_t
> fn1 (char *p, char *q)
> {
> size_t s = strlen (q);
> strcpy (p, q);
> return s - strlen (p);
> }
>
> The optimized dump shows the following:
>
> __attribute__((noclone, noinline))
> fn1 (char * p, char * q)
> {
> size_t s;
> size_t _7;
> long unsigned int _9;
>
> <bb 2>:
> s_4 = strlen (q_3(D));
> _9 = s_4 + 1;
> __builtin_memcpy (p_5(D), q_3(D), _9);
> _7 = 0;
> return _7;
>
> }
>
> which introduces the regression, because the test expects "return 0;" in fn1().
>
> The issue seems to be in vrp2:
>
> Before the patch:
> Visiting statement:
> s_4 = strlen (q_3(D));
> Found new range for s_4: VARYING
>
> Visiting statement:
> _1 = s_4;
> Found new range for _1: [s_4, s_4]
> marking stmt to be not simulated again
>
> Visiting statement:
> _7 = s_4 - _1;
> Applying pattern match.pd:111, gimple-match.c:27997
> Match-and-simplified s_4 - _1 to 0
> Intersecting
> [0, 0]
> and
> [0, +INF]
> to
> [0, 0]
> Found new range for _7: [0, 0]
>
> __attribute__((noclone, noinline))
> fn1 (char * p, char * q)
> {
> size_t s;
> long unsigned int _1;
> long unsigned int _9;
>
> <bb 2>:
> s_4 = strlen (q_3(D));
> _9 = s_4 + 1;
> __builtin_memcpy (p_5(D), q_3(D), _9);
> _1 = s_4;
> return 0;
>
> }
>
>
> After the patch:
> Visiting statement:
> s_4 = strlen (q_3(D));
> Intersecting
> [0, 9223372036854775806]
> and
> [0, 9223372036854775806]
> to
> [0, 9223372036854775806]
> Found new range for s_4: [0, 9223372036854775806]
> marking stmt to be not simulated again
>
> Visiting statement:
> _1 = s_4;
> Intersecting
> [0, 9223372036854775806] EQUIVALENCES: { s_4 } (1 elements)
> and
> [0, 9223372036854775806]
> to
> [0, 9223372036854775806] EQUIVALENCES: { s_4 } (1 elements)
> Found new range for _1: [0, 9223372036854775806]
> marking stmt to be not simulated again
>
> Visiting statement:
> _7 = s_4 - _1;
> Intersecting
> ~[9223372036854775807, 9223372036854775809]
> and
> ~[9223372036854775807, 9223372036854775809]
> to
> ~[9223372036854775807, 9223372036854775809]
> Found new range for _7: ~[9223372036854775807, 9223372036854775809]
> marking stmt to be not simulated again
>
> __attribute__((noclone, noinline))
> fn1 (char * p, char * q)
> {
> size_t s;
> long unsigned int _1;
> size_t _7;
> long unsigned int _9;
>
> <bb 2>:
> s_4 = strlen (q_3(D));
> _9 = s_4 + 1;
> __builtin_memcpy (p_5(D), q_3(D), _9);
> _1 = s_4;
> _7 = s_4 - _1;
> return _7;
>
> }
>
> Then forwprop4 turns
> _1 = s_4
> _7 = s_4 - _1
> into
> _7 = 0
>
> and we end up with:
> _7 = 0
> return _7
> in optimized dump.
>
> Running ccp again after forwprop4 trivially solves the issue, however
> I am not sure if we want to run ccp again ?
>
> The issue is probably with extract_range_from_ssa_name():
> For _1 = s_4
>
> Before patch:
> VR for s_4 is set to varying.
> So VR for _1 is set to [s_4, s_4] by extract_range_from_ssa_name.
> Since VR for _1 is [s_4, s_4] it implicitly implies that _1 is equal to s_4,
> and vrp is able to transform _7 = s_4 - _1 to _7 = 0 (by using
> match.pd pattern x - x -> 0).
>
> After patch:
> VR for s_4 is set to [0, PTRDIFF_MAX - 1]
> And correspondingly VR for _1 is set to [0, PTRDIFF_MAX - 1]
> so IIUC, we then lose the information that _1 is equal to s_4,
We don't lose it, it's in its set of equivalencies.
> and vrp doesn't transform _7 = s_4 - _1 to _7 = 0.
> forwprop4 does that because it sees that s_4 and _1 are equivalent.
> Does this sound correct ?
Yes. So the issue is really that vrp_visit_assignment_or_call calls
gimple_fold_stmt_to_constant_1 with vrp_valueize[_1] which when
we do not have a singleton VR_RANGE does not fall back to looking
at equivalences (there's not a good cheap way to do that currently because
VRP doesn't keep a proper copy lattice but simply IORs equivalences
from all equivalences). In theory simply using the first set bit
might work. Thus sth like
@@ -7057,6 +7030,12 @@ vrp_valueize (tree name)
|| is_gimple_min_invariant (vr->min))
&& vrp_operand_equal_p (vr->min, vr->max))
return vr->min;
+ else if (vr->equiv && ! bitmap_empty_p (vr->equiv))
+ {
+ unsigned num = bitmap_first_set_bit (vr->equiv);
+ if (num < SSA_NAME_VERSION (name))
+ return ssa_name (num);
+ }
}
return name;
}
might work with the idea of simply doing canonicalization to one of
the equivalences. But as we don't allow copies in the SSA def stmt
(via vrp_valueize_1) I'm not sure that's good enough canonicalization.
Richard.
More information about the Gcc-patches
mailing list