How to detect if a pointer could be within a pointer-to-struct?

For our Burst compiler at Unity, I’m adding some additional aliasing deductions as part of our ongoing work to maximize performance for our users. One case I want to have is to be able to propagate the noalias parameter attribute onto functions. While writing the torture tests for this to prove its safe, I found a very easy-to-understand problem:

struct This
{
    int* ptr;
};

void AddToPtr0(struct This* this, int* otherPtr)
{
    *otherPtr = 42;
    *this->ptr += 1;
    *this->ptr += *otherPtr;
}

// How to detect in LLVM IR that otherPtr cannot have restrict?
void AddToPtr1(struct This* restrict this, int* restrict otherPtr)
{
    *otherPtr = 42;
    *this->ptr += 1;
    *this->ptr += *otherPtr;
}

void Foo(struct This* this)
{
    AddToPtr0(this, this->ptr);
}

void Bar(struct This* this)
{
    AddToPtr1(this, this->ptr);
}

In the above example, I need to detect that otherPointer aliases with a member of the This struct at the callsite. The only way I can think to do this is to temporarily generate a bunch of GEPs + loads of all the pointer objects referenced in the This struct (will some probable cut-off depth for the evaluation), using the AAResults to work out if any of the sub-pointers also alias, and only if they don’t put a noalias on the function. Lastly I’d delete all the GEPs + loads I had to temp add.

This doesn’t seem like the most ideal approach, so I’m interested if anyone has any better ideas?

I am confused by your example and what you want to do (or not do).

Did you try to run the Attributor (-O3 -mllvm -attributor-disable=false) to get noalias annotations?

1 Like

What I want to be able to do is put restrict (noalias) on the struct This* this pointer, but not on the otherPtr (because you can get to otherPtr by going through the this pointer).

I wanted to be able to do this without having to add intermediate GEPs + loads for all the pointer fields of struct params - I need these so I can feed them into the alias analysis passes to check whether we have a noalias or not.

Since there wasn’t an immediate reply to my post saying that I’ve missed some obvious API I just went ahead and wrote code to add the GEPs + loads, do the alias calculations, and then delete them afterwards.

This works fine and I’m getting perfect noalias propagation now with my passes, but I do have to add a bunch of instructions just to remove them later!

If you have two pointers in the same scope through which you access the same object/location and neither is based on the other, then neither is restrict/noalias. restrict/noalias means exactly this situation cannot happen. I’m still unsure what difference you expect by marking one of the two pointers as restrict/noalias but not the other.

Pointers in LLVM IR are supposed to be opaque, i.e. they are not supposed to have a pointee-type.

This isn’t the case in practice today, but it is a stated long-term goal. Maybe you can solve the problem with appropriate metadata instead?