如何创建一个不会破坏严格别名的uint8_t数组? [英] How to create an uint8_t array that does not undermine strict aliasing?

查看:107
本文介绍了如何创建一个不会破坏严格别名的uint8_t数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近问过这个问题:



使用此指针在热循环中导致奇怪的去优化



问题是我正在写一个类型的数组 uint8_t ,并且编译器将其视为可以使用方法的 this 指针$ c> struct T * ),因为 void * code> uint8_t * )可以总是别名C ++中的任何其他指针。此行为导致错过优化机会。我想避免这一点,当然。所以问题是:我可以声明一个强制执行严格别名的 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 *>
/ **`this-> target`不能被缓存在这里的寄存器中,但
被重载16次,因为编译器
认为`this-> target`可能是别名与this本身。
我想要的是一个特殊的uint8_t类型,不会触发
这种行为。 * /
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;
}
}
};


解决方案

您可以使用 struct :



<$ 类型p $ p> struct X {uint8_t i:CHAR_BIT; X(uint8_t i):i(i){}};

这似乎消除了别名pessimization(用gcc 4.9.0测试): http://goo.gl/S1NbsB



即使 [t] bit-field属性不是类成员类型的一部分 [class.bit] / 1)使成员位字段似乎必要de -pessimize the generated code。


I recently asked this question:

Using this pointer causes strange deoptimization in hot loop

The problem was that I was writing to an array of type uint8_t and the compiler treated it as if it could alias with the this pointer of the method (of type struct T*), because void* and char* (=uint8_t*) can always alias any other pointer in C++. This behaviour caused a missed optimization opportunity. I want to avoid this, of course. So the question is: Can I declare an uint8_t array that enforces strict aliasing, i.e., that the compiler treats as never aliased with any pointer of another type? I.e., I am looking for something like a strict_uint8_t type that is an uint8_t with special aliasing behaviour. Is there a way to achieve this?

Example code to show what I mean, borrowed from other question and simplified. For more details, read the linked question and its accepted answer:

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;
        }
}
};

解决方案

You can use a struct type (i.e. a strong typedef) backed by a bitfield with base type uint8_t:

struct X { uint8_t i : CHAR_BIT; X(uint8_t i) : i(i) {} };

This appears to eliminate the aliasing pessimization (tested with gcc 4.9.0): http://goo.gl/S1NbsB

Even though "[t]he bit-field attribute is not part of the type of the class member" ([class.bit]/1) making the member a bit-field seems necessary to de-pessimize the generated code.

这篇关于如何创建一个不会破坏严格别名的uint8_t数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆