> On Apr 8, 2025, at 13:13, Siddhesh Poyarekar <[email protected]> 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