On 2023-08-16 11:59, Qing Zhao wrote:
Jakub and Sid,
During my study, I found an interesting behavior for the following small
testing case:
#include <stddef.h>
#include <stdio.h>
struct fixed {
size_t foo;
char b;
char array[10];
} q = {};
#define noinline __attribute__((__noinline__))
static void noinline bar ()
{
struct fixed *p = &q;
printf("the__bos of MAX p->array sub is %d \n",
__builtin_object_size(p->array, 1));
printf("the__bos of MIN p->array sub is %d \n",
__builtin_object_size(p->array, 3));
return;
}
int main ()
{
bar ();
return 0;
}
[opc@qinzhao-aarch64-ol8 108896]$ sh t
/home/opc/Install/latest-d/bin/gcc -O -fstrict-flex-arrays=3 t2.c
the__bos of MAX p->array sub is 10
the__bos of MIN p->array sub is 15
I assume that the Minimum size in the sub-object should be 10 too (i.e
__builtin_object_size(p->array, 3) should be 10 too).
So, first question: Is this correct or wrong behavior for
__builtin_object_size(p->array, 3)?
The second question is, when I debugged into why
__builtin_object_size(p->array, 3) returns 15 instead of 10, I observed the
following:
1. In “early_objz” phase, The IR for p->array is:
(gdb) call debug_generic_expr(ptr)
&p_5->array
And the pt_var is:
(gdb) call debug_generic_expr(pt_var)
*p_5
As a result, the following condition in tree-object-size.cc:
585 if (pt_var != TREE_OPERAND (ptr, 0))
Was satisfied, and then the algorithm for computing the SUBOBJECT was invoked
and the size of the subobject 10 was used.
and then an MAX_EXPR was inserted after the __builtin_object_size call as:
_3 = &p_5->array;
_10 = __builtin_object_size (_3, 3);
_4 = MAX_EXPR <_10, 10>;
Till now, everything looks fine.
2. within “ccp1” phase, when folding the call to __builtin_object_size, the IR
for the p-:>array is:
(gdb) call debug_generic_expr(ptr)
&MEM <char[10]> [(void *)&q + 9B]
And the pt_var is:
(gdb) call debug_generic_expr(pt_var)
MEM <char[10]> [(void *)&q + 9B]
As a result, the following condition in tree-object-size.cc:
585 if (pt_var != TREE_OPERAND (ptr, 0))
Was NOT satisfied, therefore the algorithm for computing the SUBOBJECT was NOT
invoked at all, as a result, the size in the whole object, 15, was used.
And then finally, MAX_EXPR (_10, 10) becomes MAX_EXPR (15, 10), 15 is the final
result.
Based on the above, is there any issue with the current algorithm?
So this is a (sort of) known issue, which necessitated the early_objsz
pass to get an estimate before a subobject reference was optimized to a
MEM_REF. However it looks like the MIN/MAX hack doesn't work in this
case for OST_MINIMUM; it should probably get the minimum of the two
passes if both passes were successful, or only the result of the pass
that was successful.
Thanks,
Sid