What does GCC use instead of GEP?

Viewed 60

Of the two best-known C compilers, LLVM handles address calculation of elements of compound objects with the somewhat notorious getelementptr instruction, which is perhaps most readably discussed in https://blog.yossarian.net/2020/09/19/LLVMs-getelementptr-by-example

But basically the most conspicuous feature of GEP, as far as I can see, is that it is unique among LLVM instructions in putting an arbitrarily long sequence of calculations into one instruction. I haven't been able to find any explanation of why it was decided to do this instead of breaking it up into several LEA instructions each performing a single calculation.

What does GCC use instead?

Godbolt doesn't seem to provide IR output for GCC, so I took an example from the above page:

typedef struct foo {
  struct {
    long field1;
    struct {
      long field2;
      long field3;
      union {
        long field4;
        char field5[32];
      } quux;
      long field6;
      long field7;
    } baz;
    long field8;
  } bar;
} foo;

foo chunky;

char take_field(void) {
  return chunky.bar.baz.quux.field5[17];
}

Compiled with gcc -fdump-tree-all a.c and got, among other things, a.c.020t.ssa with the following contents:

;; Function take_field (take_field, funcdef_no=0, decl_uid=1810, cgraph_uid=0, symbol_order=1)

take_field ()
{
  char D.1813;
  char _2;

  <bb 2> [0.00%]:
  _2 = chunky.bar.baz.quux.field5[17];

<L0> [0.00%]:
  return _2;

}

Now, I wouldn't have been surprised to see it doing the same thing as LLVM.

I also wouldn't have been surprised to see it breaking up the big address calculation into a sequence of smaller calculations.

But from what I can see, what it actually does is just squashes all the calculations together into a single 'add 17'.

Is this how GCC handles address calculations in general? If so... I sort of want to ask why it does this, but I suppose the real question would be the other way around: if that suffices, then other things equal, simpler is clearly better, so if that suffices, why does LLVM use the more complex form that places an arbitrarily long sequence of calculations in one instruction? Is there a disadvantage in squashing it into a single number? Or if there is a disadvantage, then why does GCC do that?

0 Answers
Related