> On Apr 8, 2025, at 13:13, Siddhesh Poyarekar <siddh...@gotplt.org> wrote: > > On 2025-04-08 12:41, Qing Zhao wrote: >> For the following small example: >> [ counted_by_whole]$ cat t.c >> #include <stdlib.h> >> #include <stddef.h> >> struct annotated { >> size_t count; >> char other; >> char array[] __attribute__((counted_by (count))); >> }; >> #define MAX(A, B) (A > B) ? (A) : (B) >> #define ALLOC_SIZE_ANNOTATED(COUNT) \ >> MAX(sizeof (struct annotated), \ >> offsetof(struct annotated, array[0]) + (COUNT) * sizeof(char)) >> static struct annotated * __attribute__((__noinline__)) alloc_buf (int index) >> { >> struct annotated *p; >> p = (struct annotated *) malloc (ALLOC_SIZE_ANNOTATED(index)); >> p->count = index; >> return p; >> } >> int main() >> { >> struct annotated *q = alloc_buf (10); >> __builtin_printf ("the bdos whole is %d\n", >> __builtin_dynamic_object_size(q, 1)); >> return 0; >> } >> The gimple IR is: >> 1 int main () >> 2 { >> 3 int D.5072; >> 4 >> 5 { >> 6 struct annotated * q; >> 7 >> 8 q = alloc_buf (10); >> 9 _1 = __builtin_dynamic_object_size (q, 1); >> 10 __builtin_printf ("the bdos whole is %d\n", _1); >> 11 D.5072 = 0; >> 12 return D.5072; >> 13 } >> 14 D.5072 = 0; >> 15 return D.5072; >> 16 } >> 17 >> 18 >> 19 __attribute__((noinline)) >> 20 struct annotated * alloc_buf (int index) >> 21 { >> 22 struct annotated * D.5074; >> 23 struct annotated * p; >> 24 25 _1 = (long unsigned int) index; >> 26 _2 = _1 + 9; >> 27 _3 = MAX_EXPR <_2, 16>; >> 28 p = malloc (_3); >> 29 _4 = (long unsigned int) index; >> 30 p->count = _4; >> 31 D.5074 = p; >> 32 return D.5074; >> 33 } >> When we generate the .ACCESS_WITH_SIZE for a pointer reference to “struct >> annotated”, >> Looks like all the pointer references, at line 8, “q”, at line 9, “q”, at >> line 28, “p”, need to be changed >> to a call to .ACCESS_WITH_SIZE. this might increase the IR size >> unnecessarily. Might have some >> Impact on the inlining decision heuristics or other heuristic that depend on >> the code size. >> Not sure whether this is a concern or not. > > On the general question of whether additional .ACCESS_WITH_SIZE could hinder > optimizations, one effect may be that it ends up acting as a barrier > preventing code reordering around it, which may miss some opportunities. > However IMO that preserves correctness anyway.
Changing a pointer reference to a call to .ACCESS_WITH_SIZE will impact the compiler optimization in two aspects: 1. The new call site might become a barrier that prevents code movement around it. 2. Increased insn counts might impact the compiler heuristics that depends on code size. The above 1 can be alleviated by proper marking of the routine .ACCESS_WITH_SIZE: Currently, .ACCESS_WITH_SIZE is marked as a PURE function: /* A function to associate the access size and access mode information with the corresponding reference to an object. It only reads from the 2nd argument. */ DEF_INTERNAL_FN (ACCESS_WITH_SIZE, ECF_PURE | ECF_LEAF | ECF_NOTHROW, NULL) I think that this marking (ECF_PURE) should avoid most of the missed optimizations of 1. For 2, When generating .ACCESS_WITH_SIZE to FAM references currently, one reference REF will become: (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1, (TYPE_OF_ARRAY *)0)) It increase the # of IRs, but not that much. However, when generating .ACCESS_WITH_SIZE to a pointer REF to a structure with FAM, one reference will become: If (!type_unsigned (typeof (ref->c)) ref->c = (ref->c < 0) ? 0 : ref->c; sz_exp = MAX (sizeof (struct S), offset (struct S, a) + ref->c * sizeof (char)); ref = .ACCESS_WITH_SIZE (&ref, &sz_exp, 0, …); It’s obviously that the # if IRs will increase quite a lot for one pointer REF. So, I am a little concern on this impact. If the only consumer of the counted_by information is _bdos, then it might not worth to change all the pointer ref to call to .ACCESS_WITH_SIZE. > > On the other hand though, .ACCESS_WITH_SIZE should ideally provide range > information that could aid optimization or even diagnostics. It's not > something we do at the moment AFAIK though, except when .ACCESS_WITH_SIZE > feeds directly into a __bos/__bdos call, in which case the __bos/__bdos call > ends up providing that hint (I think). > > Andrew, is this something pranger could explicitly identify? That is, use > .ACCESS_WITH_SIZE calls to identify the range of the pointer it is called > with? Yes, if there are other consumers to the counted_by information in general, generating call to .ACCESS_WITH_SIZE in C FE might be better. Thanks. Qing > > Thanks, > Sid