> 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

Reply via email to