Aliasing is when two pointers overlap in used memory space, this can happen for a variety of reasons but introduces very subtle dependencies which limit optimizations, let's walk through a simple example:
int foo(int* a, int* b) {
*a = 0;
*b = 1;
return *a;
}In this example if a and b refer to the same location then we return 1 since *a is dependent on the value of *b which means we couldn't constant fold the output to zero. This doesn't matter much here but once you imagine that all pointers can be anything at any time then you've introduced metric tons of dependencies you have to manage, so how do we do that? well we begin to classify that certain memory objects can't alias and that put different pointers into those different boxes.
Pointer are described as having provenance which is knowledge of the memory object they exist inside of. The first place we can start looking for provenance is in pointers derived from others, we know that a[0] and a[1] exist in the same object so they "may alias" but since both refer to distinct regions we know that they don't.
int foo(int* a) {
a[0] = 0;
a[1] = 1;
return a[0]; // we can constant fold this into 0 now
}This simple idea has cut down a variety of very simple aliasing problems such as writing to different array elements or even writing to members of a struct. We can expand further when we realize that the mere act of allocating memory is a way of solving for provenance.