getelementptr

Hello,

I wonder if the getelementptr can have other successors than load, store in some other cases when I directly print or directly return the result. every time I would like to assign the result - it will have a load/store successor?

So, basically the overall question is to clarify the possible successors of getelementptr.

Any instruction that may take a pointer operand might be a user of a GEP. For example, consider this C function:

int x(struct S *s)
{
  y(&s->field);
}

Here, there will be a GEP to get the address of the field and then the user will be a call (or possibly invoke) instruction.

David

Ok, thank you. I have also one question about getelementptr. In different versions of clang I see that sometimes array[i][i] is preceded by two getelementptr instructions and sometimes only by one - with an already complex index.

Is there a way to set always a defined behavior here - for example that we will always one getelemntptr with complex index?

This thread from June: http://lists.llvm.org/pipermail/llvm-dev/2017-June/114108.html

this is about a pass that can split GEPs into multiple equivalent GEPs, without changing the overall meaning. Presumably the reverse operation of merging GEPs might also be a reasonable LLVM canonicalisation pass, though I don’t think it is implemented at the moment.

If anyone knows why merging two GEPs is not equivalent to performing them one after the other, I’d love to know. I suppose the inbounds keyword may wreak havoc with the semantics.

Sam

No.
It would be helpful to understand what you are trying to accomplish overall, which may help people give you details about the best way to accomplish it.
For example, if you are trying to understand or recover array indexes from GEP’s, that is non-trivial.

So, I am trying to do smth like this. Basically, we are developing are own hls tool for fpga based on llvm. Getelementptr is not representable in hardware (as far as I understand, I am here a person , who deals with llvm mostly). The easiest case will be to derive the index and pass it to memory controller, which is connected to load and store instructions. However, when there is a getelementptr for structures - the things become too complicated to derive the offset (index). So, by now I am trying to understand what are rules for getelementptr in code, what can be it’s successors , what can be it’s predecessors in order to come to another solution.

I also looked at some examples and I noticed that these too function declaration result in totally different code:
#define N 100
void pivot (int x, int a[N], int n, int k) {

void pivot (int *x, int **a, int n, int k) {

To access element if array a, in the second case I have to do a load at first , after getelementptr of the first dimension and then make getelementptr again : 

getelementptr->load->getelementptr.

In the first case there is only one getelementptr on the two dimensions simultaneously(getelementptr with three arguments) : getelementptr->load.

What is the difference? 

I think the last question about getelementptr, is why:
else if (isa(*GEP.idx_begin()) &&
cast(*GEP.idx_begin())->isNullValue() &&
Src->getNumOperands() != 1) {
// Otherwise we can do the fold if the first index of the GEP is a zero

why we can fold only if the first argument is zero? What wrong will happen if I will have first offset 1?

That’s pretty fundamental.

#define N 100
void pivot (int x, int a[N], int n, int k) {

a is a single block of memory, some unknown multiple of 400 bytes (100*sizeof(int)) long. When accessing it, the first index is multiplied by 400 and added to the second index multiplied by 4. This could be expressed by two successive GEPs or (a little better, and the reason for GEP) by a single combined GEP.

void pivot (int *x, int **a, int n, int k) {

a is a block of memory containing an unknown number of pointers, with each pointer pointing at a block of memory containing an unknown number of ints. If you write a[y] then x is multiplied by sizeof(void*) and added to a. The pointer at that location is loaded, and added to y*sizeof(int) to get the final address. Two loads are unavoidable, and this can not be collapsed into a single GEP. GEP never accesses memory.

I don’t know why GEP wouldn’t be expressible by hardware. Obviously CPUs are hardware. Perhaps what you mean is that you need the result of the GEP to be resolved at compile time, which means that the original pointer must be the address of a static variable, and the indices must all be constant.

If you’re trying to compile C to hardware, then you’d want an earlier pass to convert function locals from auto to static, and at the same time prove there is no recursion.