Issue 164225
Summary [X86] Poor codegen when accessing a single bit of very large integers
Labels missed-optimization, llvm:SelectionDAG
Assignees
Reporter RKSimon
    ```c
bool get512(_BitInt(512) x, unsigned i) {
    _BitInt(512) k = 1;
    return (x & (k << i)) != 0;
}
```
results in a huge amount of expanded shift and bit logic, even though we know that we could access a single legal word directly (assumes little endian):
```c
bool get512m(_BitInt(512) x, unsigned i) {
 i %= 512; // not really necessary, but basic bounds check
    const uint64_t *p = (const uint64_t *)&x;
    uint64_t r = p[i / 64];
    return (r & (1 << (i/64))) != 0;
}
```
Cases where we're altering single bits could be simplified similarly:
```c
void clear512(_BitInt(512) &x, unsigned i) {
    _BitInt(512) k = 1;
    x &= ~(k << i);
}
void flip512(_BitInt(512) &x, unsigned i) {
    _BitInt(512) k = 1;
    x ^= (k << i);
}
void set512(_BitInt(512) &x, unsigned i) {
    _BitInt(512) k = 1;
    x |= (k << i);
}
void init512(_BitInt(512) &x, bool v, unsigned i) {
    _BitInt(512) k = 1;
    _BitInt(512) m = (unsigned)v & 1;
    x &= ~(k << i);
    x |= (m << i);
}
```
vs
```c
void clear512m(_BitInt(512) &x, unsigned i) {
    i %= 512;
    uint64_t *p = (uint64_t *)&x;
 uint64_t *r = p + (i / 64);
    *r &= ~(1 << (i % 64));
}
void flip512m(_BitInt(512) &x, unsigned i) {
    i %= 512;
    uint64_t *p = (uint64_t *)&x;
    uint64_t *r = p + (i / 64);
    *r ^= ~(1 << (i % 64));
}
void set512m(_BitInt(512) &x, unsigned i) {
    i %= 512;
 uint64_t *p = (uint64_t *)&x;
    uint64_t *r = p + (i / 64);
    *r |= (1 << (i % 64));
}
void init512m(_BitInt(512) &x, bool v, unsigned i) {
    i %= 512;
    uint64_t *p = (uint64_t *)&x;
    uint64_t *r = p + (i / 64);
 *r &= ~(1 << (i % 64));
    *r |= (((unsigned)v & 1) << (i % 64));
}
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to