https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87245

            Bug ID: 87245
           Summary: [missed optimization] switching on indices of struct
                    members
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: herring at lanl dot gov
  Target Milestone: ---

Consider a simple struct whose members can be accessed by name or by index:

  struct vec {double x,y,z;};

  double get(const struct vec *v,unsigned long i) {
    switch(i) {
      case 0: return v->x;
      case 1: return v->y;
      case 2: return v->z;
    }
  }

Godbolt's trunk x86_64 build produces at -O3

  get:
    cmpq $1, %rsi
    ja .L2
    je .L11
    movsd (%rdi), %xmm0
    ret
  .L2:
    cmpq $2, %rsi
    jne .L12
    movsd 16(%rdi), %xmm0
    ret
  .L11:
    movsd 8(%rdi), %xmm0
    ret
  .L12:
    ret

when of course

  get:
    movsd (%rdi,%rsi,8), %xmm0
    ret

would suffice.  (Apologies if I picked the wrong -optimization component.)

Bonus points for collapsing

  double get(const struct vec *arr,unsigned long i) {
    arr+=i/3;
    switch(i%3) {
      case 0: return arr->x;
      case 1: return arr->y;
      case 2: return arr->z;
    }
  }

to the same two instructions.

Reply via email to