On 2023-08-17 15:27, Qing Zhao wrote:
Yes, that's it. Maybe it's more correct if instead of MAX_EXPR if for
OST_MINIMUM we stick with the early_objsz answer if it's non-zero. I'm not
sure if that's the case for maximum size though, my gut says it isn't.
So, the major purpose for adding the early object size phase is for computing
SUBobjects size more precisely before the subobject information lost?
I suppose it's more about being able to do it at all, rather than precision.
Then, I think whatever MIN or MAX, the early phase has more precise information
than the later phase, we should use its result if it’s NOT UNKNOWN?
We can't be sure about that though, can we? For example for something
like this:
struct S
{
int a;
char b[10];
int c;
};
size_t foo (struct S *s)
{
return __builtin_object_size (s->b, 1);
}
size_t bar ()
{
struct S *in = malloc (8);
return foo (in);
}
returns 10 for __builtin_object_size in early_objsz but when it sees the
malloc in the later objsz pass, it returns 4:
$ gcc/cc1 -fdump-tree-objsz-details -quiet -o - -O bug.c
...
foo:
.LFB0:
.cfi_startproc
movl $10, %eax
ret
.cfi_endproc
...
bar:
.LFB1:
.cfi_startproc
movl $4, %eax
ret
.cfi_endproc
...
In fact, this ends up returning the wrong result for OST_MINIMUM:
$ gcc/cc1 -fdump-tree-objsz-details -quiet -o - -O bug.c
...
foo:
.LFB0:
.cfi_startproc
movl $10, %eax
ret
.cfi_endproc
...
bar:
.LFB1:
.cfi_startproc
movl $10, %eax
ret
.cfi_endproc
...
bar ought to have returned 4 too (and I'm betting the later objsz must
have seen that) but it got overridden by the earlier estimate of 10.
We probably need smarter heuristics on choosing between the estimate of
the early_objsz and late objsz passes each by itself isn't good enough
for subobjects.
Thanks,
Sid