> On Aug 17, 2023, at 7:00 AM, Siddhesh Poyarekar <siddh...@gotplt.org> wrote: > > 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.
Do you mean that after a subobject reference was optimized to a MEM_REF, there is no way to compute the size of the subobject anymore? > 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. You mean that the following line: 2053 enum tree_code code = object_size_type & OST_MINIMUM ? MAX_EXPR : MIN_EXPR; Might need to be changed to: 2053 enum tree_code code = MIN_EXPR; ? thanks. Qing > > Thanks, > Sid