[InstSimplify] Remove zero-index opaque pointer GEP

Hi. I’m trying to understand how opaque pointers work with GEPs. Consider below case.
Link: Compiler Explorer

%a = getelementptr inbounds [2 x [1 x float]], ptr @aaa, i64 0, i64 %in1
%b = getelementptr inbounds [1 x float], ptr %a, i64 0, i64 0
%c = getelementptr inbounds float, ptr %b, i64 %in2

After this change: link, which makes all zero index GEP as no-op :

%a = getelementptr inbounds [2 x [1 x float]], ptr @aaa, i64 0, i64 %in1
%c = getelementptr inbounds float, ptr %a, i64 %in2

%a ResultElementType is [1xfloat]
%c expects float pointer type as input, but gets [1 x float].

Is this valid in opaque pointers case?

Yes, it’s legal, in opaque pointer mode, for a GEP of a GEP instruction to have the source element type of the second GEP not match the result element type of the first GEP.

For opaque pointers, the type of a, b and c in your example are all of type “ptr”. Not float or anything else.
For your examples, it might be easier to understand if you create some C source code, and the compile it with clang-15 and the see what sort of gep expressions happen.

1 Like

%a = getelementptr inbounds [2 x [1 x float]], ptr @aaa, i64 0, i64 %in1
%c = getelementptr inbounds float, ptr %a, i64 %in2

%x = getelementptr inbounds [2 x [1 x float]], ptr @aaa, i64 0, i64 %in1, i64 %in2

@jcranmer Thanks for clarifying.
since %c has only one index, %a and %c could be merged to %x, single GEP instruction ?
This optimisation happens if we didn’t have opaque pointers: link

The GEPs can be merged only if GEP2->getSourceElementType() == GEP1->getResultElementType(). With typed pointers, this is true for every gep-of-gep, but this is not the case for opaque pointers, and a few optimizations have had to be fixed to make sure that they check for this precondition.