-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Closed
Copy link
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));
}