- Notifications
You must be signed in to change notification settings - Fork 15k
Closed
Description
https://godbolt.org/z/WG3fK6vaz
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):
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:
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
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)); }