On 6/17/20 4:37 PM, Jeff Law via Gcc-patches wrote:
On Wed, 2020-06-17 at 10:04 +0200, Jakub Jelinek via Gcc-patches wrote:
On Wed, Jun 17, 2020 at 09:13:25AM +0200, Richard Biener via Gcc-patches wrote:
Not doing the transformation I suggest at all, or not doing it in
cases when the member does match the source?
We are currently not treating different fields at the same offset as
"equal" before inlining completed for objsize to "work", thus leaving
optimizations on the plate.
As the first objsz pass runs quite early (the second one in
pass_all_early_optimizations), we could just add a property for that
and use it instead of the cfun->after_inlining check.
And after that pass, we should be remembering the field limits in the IL
explicitly as a MIN/MAX_EXPR for the bos call.
Right. And that's part of the reason why I was suggesting we attach original
type information to the calls (and perhaps other *_REF nodes) as early in the
pipeline as possible -- the earlier in the pipeline we are, the closer the IL is
to the source and the more likely that type information will be correct.
I'm not wed to that idea, but I do think we need to start moving away from
walking the use-def chains to find an address computation which may have a type
with little/no relation to the object we're modifying. I think it's become
clear
that's ultimately a losing battle.
Take this example detected by -Wstringop-overflow:
void g (void*);
void f (int n)
{
if (n < 3 || 5 < n)
n = 3;
char a[n];
memset (a + 1, 0, 7);
g (a);
}
Everything there is to attach to the memset call is already there
but it isn't enough to detect the overflow:
<bb 4> [local count: 1073741824]:
# _8 = PHI <n_3(D)(2), 3(3)>
prephitmp_16 = (sizetype) _8;
a.2_11 = __builtin_alloca_with_align (prephitmp_16, 8);
_9 = a.2_11 + 1;
__builtin_memset (_9, 0, 7);
To avoid the walk we'd have to associate not only the object size
with every pointer, but also the pointer's offset into the object
(the remaining size alone isn't good enough when pointers are
decremented).
I have a working prototype of this for the path isolation pass
where we have talked about moving -Warray-bounds, but it tracks
these sizes and offsets (and more) outside the IL, and it still
walks the use-def chains. It could be reworked to build up
the database as it's walking the CFG forward (in fact, it does
both), but either way, it has to do a walk and follow the pointer
assignments.
As an aside, it feels reminiscent of the on-demand VRP that Aldy
& Andrew are working on: a way to query a pointer for ranges of
object sizes.
Except to provide quality diagnostics and avoid multiple passes
over the CFG the database has to also track the identities of
the objects (so it can point to them in diagnostics), and besides
size (and offset) track all the other properties of interest,
such as:
* are any of the objects const, or pointer arguments
declared const restrict? (for -Write-const)
* are any local variables? (for -Wreturn-local-addr)
* are any dynamically allocated (for -Wfree-nonheap-object)
* are any of them VLA function parameters or arrays declared
[static N] (for -Wstringop-overflow)
* are any pointers to non-local variables in const/pure
functions (for -Waccess-by-const-or-pure-function)
...
(Besides bearing a superficial resemblance to VRP it also seems
like an enhancement for points-to analysis.)
Martin