Недавно я задал этот вопрос:
Использование этого указателя вызывает странную деоптимизацию в горячем цикле
Проблема заключалась в том, что я писал массив типа uint8_t
, и компилятор рассматривал его так, как если бы он мог быть псевдонимом с указателем this
метода (типа struct T*
), потому что void*
и char*
(= uint8_t*
) всегда может быть любым другим указателем на С++. Такое поведение вызвало упущенную оптимизацию. Конечно, я хочу этого избежать. Поэтому возникает вопрос: могу ли я объявить массив uint8_t
, который обеспечивает строгое сглаживание, т.е. Что компилятор рассматривает как никогда не псевдонимы с любым указателем другого типа? Я., я ищу что-то вроде типа strict_uint8_t
, который является uint8_t
со специальным псевдонимом. Есть ли способ достичь этого?
Пример кода, чтобы показать, что я имею в виду, заимствован из другого вопроса и упрощен. Для получения дополнительной информации прочитайте связанный вопрос и его принятый ответ:
struct T{
uint8_t* target;
void unpack3bit(char* source, int size) {
while(size > 0){
uint64_t t = *reinterpret_cast<uint64_t*>(source);
/** `this->target` cannot be cached in a register here but has
to be reloaded 16 times because the compiler
thinks that `this->target` could alias with `this` itself.
What I want is a special uint8_t type that does not trigger
this behaviour. */
this->target[0] = t & 0x7;
this->target[1] = (t >> 3) & 0x7;
this->target[2] = (t >> 6) & 0x7;
this->target[3] = (t >> 9) & 0x7;
this->target[4] = (t >> 12) & 0x7;
this->target[5] = (t >> 15) & 0x7;
this->target[6] = (t >> 18) & 0x7;
this->target[7] = (t >> 21) & 0x7;
this->target[8] = (t >> 24) & 0x7;
this->target[9] = (t >> 27) & 0x7;
this->target[10] = (t >> 30) & 0x7;
this->target[11] = (t >> 33) & 0x7;
this->target[12] = (t >> 36) & 0x7;
this->target[13] = (t >> 39) & 0x7;
this->target[14] = (t >> 42) & 0x7;
this->target[15] = (t >> 45) & 0x7;
source+=6;
size-=6;
target+=16;
}
}
};