Issue 136473
Summary Missed optimization: switch with GEP inside cannot generate lookup table
Labels new issue
Assignees
Reporter oxalica
    [C godbolt](https://godbolt.org/z/exoPTKKPa) 
I'm expecting `selector1` to be optimized to `selector2`. But the optimizer cannot treat constant GEP as add in order to hoist the common `s + _` out of switch.

[IIUC](https://llvm.org/docs/GetElementPtr.html#how-is-gep-different-from-ptrtoint-arithmetic-and-inttoptr), `getelementptr` carries more (aliasing) information and should be more efficient than direct pointer arithmetic, but it seems to be worse than simple pointer arithmetic in this case.

Similar issue: #33633 is about homogeneous struct, while this issue is about heterogeneous struct. I'm not sure if this is considered the same, because in this case, we cannot simply cast the pointer into `[4 x i32]`, a lookup table is necessary.

Origin: I run into this issue on Rust [godbolt](https://godbolt.org/z/6s8jbYhEP), where it's hard to do `offset_of` workaround even with `unsafe`, because of the need to attach type-related vtable to each pointer.

```c
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct {
 uint8_t a;
    uint8_t b;
    uint16_t c;
    uint32_t d;
    uint64_t e;
    float f;
    double g;
} S;

/* indirect jump, with LEA+RET in each branch */
void *selector1(S *s, int i) {
    switch (i) {
 case 0: return &s->a;
        case 1: return &s->b;
        case 2: return &s->c;
        case 3: return &s->d;
        case 4: return &s->e;
 case 5: return &s->f;
        case 6: return &s->g;
        default: return NULL;
    }
}

/* indirect load, ADD */
void *selector2(S *s, int i) {
 size_t off;
    switch (i) {
        case 0: off = offsetof(S, a); break;
        case 1: off = offsetof(S, b); break;
        case 2: off = offsetof(S, c); break;
        case 3: off = offsetof(S, d); break;
 case 4: off = offsetof(S, e); break;
        case 5: off = offsetof(S, f); break;
        case 6: off = offsetof(S, g); break;
        default: return NULL;
    }
    return (uint8_t *)s + off;
}

```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to