On Mon, Aug 21, 2017 at 10:10 PM, Martin Sebor <[email protected]> wrote:
> On 08/09/2017 10:14 AM, Jeff Law wrote:
>>
>> On 08/06/2017 05:08 PM, Martin Sebor wrote:
>>
>>>>
>>>> Well, simply because the way as implemented isn't a must-alias query
>>>> but maybe one that's good enough for warnings (reduces false positives
>>>> but surely doesn't eliminate them).
>>>
>>>
>>> I'm very interested in reducing the rate of false positives in
>>> these and all other warnings. As I mentioned in my comments,
>>> I did my best to weed them out of the implementation by building
>>> GDB, Glibc, Busybox, and the Linux kernel. That of course isn't
>>> a guarantee that there aren't any. But the first implementation
>>> of any non-trivial feature is never perfect, and hardly any
>>> warning of sufficient complexity is free of false positives, no
>>> matter here it's implemented (the middle-end, front-end, or
>>> a standalone static analysis tool). If you spotted some cases
>>> I had missed I'd certainly be grateful for examples. Otherwise,
>>> they will undoubtedly be reported as more software is exposed
>>> to the warning and, if possible, fixed, as happens with all
>>> other warnings.
>>
>> I think Richi is saying that the must alias query you've built isn't
>> proper/correct. It's less about false positives for Richi and more
>> about building a proper must alias query if I understand him correctly.
>>
>> I suspect he's also saying that you can't reasonably build must-alias on
>> top of a may-alias query framework. They're pretty different queries.
>>
>> If you need something that is close to, but not quite a must alias
>> query, then you're going to have to make a argument for that and you
>> can't call it a must alias query.
>
>
> Attached is an updated and simplified patch that avoids making
> changes to any of the may-alias functions. It turns out that
> all the information the logic needs to determine the overlap
> is already in the ao_ref structures populated by
> ao_ref_init_from_ptr_and_size. The only changes to the pass
> are the enhancement to ao_ref_init_from_ptr_and_size to make
> use of range info and the addition of the two new functions
> used by the -Wrestrict clients outside the pass.
Warning for memcpy (p, p, ...) is going to fire false positives all around
given the C++ FE emits those in some cases and optimization can
expose that we are dealing with self-assignments. And *p = *p is
valid.
@@ -1028,6 +1066,10 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
}
}
+ /* Avoid folding the call if overlap is detected. */
+ if (check_overlap && detect_overlap (loc, stmt, dest, src, len))
+ return false;
+
no, please not. You diagnosed the call (which might be a false positive)
so why keep it undefined? The folded stmt will either have the same
semantics (aggregate copies expanded as memcpy) or have all reads
performed before writes.
The ao_ref_init_from_ptr_and_size change misses a changelog entry.
+detect_overlap (location_t loc, gimple *stmt, tree dst, tree src, tree size,
+ bool adjust /* = false */)
+{
+ ao_ref dstref, srcref;
+ unsigned HOST_WIDE_INT range[2];
+
+ /* Initialize and store the lower bound of a constant offset (in
+ bits), disregarding the offset for the destination. */
+ ao_ref_init_from_ptr_and_size (&dstref, dst, size, range);
+ ao_ref_init_from_ptr_and_size (&srcref, src, size, range);
just pass NULL range to the first call?
- ref->ref = NULL_TREE;
+
+ if (offrng)
+ offrng[0] = offrng[1] = 0;
+
+ ref->ref = NULL_TREE;
bogus indent
+ else if (offrng && TREE_CODE (offset) == SSA_NAME)
+ {
+ wide_int min, max;
+ value_range_type rng = get_range_info (offset, &min, &max);
+ if (rng == VR_RANGE && wi::fits_uhwi_p (min))
+ {
+ ptr = gimple_assign_rhs1 (stmt);
+ offrng[0] = BITS_PER_UNIT * min.to_uhwi ();
+ offrng[1] = BITS_PER_UNIT * max.to_uhwi ();
+
+ extra_offset = offrng[0];
you didnt' check whether max fits uhwi. The effect of passing offrng
is not documented.
+ else
+ /* Offset range is indeterminate. */
+ offrng[0] = offrng[1] = HOST_WIDE_INT_M1U;
I believe a cleaner interface would be to do
void
ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size, tree
*var_byte_offset)
and set *var_byte_offset to your 'offset' above, leaving 'ref'
unchanged. The caller
can then get at the range info of var_byte_offset and adjust
ref->offset if desired.
The indeterminate state is then much cleaner - NULL_TREE.
+unsigned HOST_WIDE_INT
+refs_overlap (ao_ref *ref1, ao_ref *ref2, unsigned HOST_WIDE_INT *aloff)
+{
bool
refs_must_overlap_p (ao_ref *, ao_ref *, unsigned HOST_WIDE_INT *off,
unsinged HOST_WIDE_INT *size)
your return values are in bytes thus
+
+ // Compare pointers.
+ offset1 += mem_ref_offset (base1) << LOG2_BITS_PER_UNIT;
+ offset2 += mem_ref_offset (base2) << LOG2_BITS_PER_UNIT;
+ base1 = TREE_OPERAND (base1, 0);
just do the intermediate computations in bytes as well.
It looks like it is unspecified relative to which ref the offset is given,
how's that useful information then -- the diagnostic doesn't seem
too helpful? Why not keep it relative to the first ref and thus make
aloff signed?
detect_overlap doesn't belong to tree-ssa-alias.[ch].
(didn't look at the diagnostic parts)
Thanks,
Richard.
> Martin