优化C中的位解码操作

Mar*_*rco 3 c performance bit-manipulation

我有一个无符号的32位整数,按以下方式编码:

  • 前6位定义了 opcode
  • 接下来的8位定义了一个 register
  • 接下来的18位是二进制补码有符号整数value.

我正在使用以下方法解码此数字(uint32_t inst):

const uint32_t opcode = ((inst >> 26) & 0x3F);
const uint32_t r1 = (inst >> 18) & 0xFF;
const int32_t value = ((inst >> 17) & 0x01) ? -(131072 - (inst & 0x1FFFF)) : (inst & 0x1FFFF);
Run Code Online (Sandbox Code Playgroud)

我可以在解码值时测量显着的开销,我很确定这是由于三元运算符(基本上是if语句)用于比较符号执行否定操作.

有没有办法以更快的方式执行值解码?

Joh*_*ger 5

你的表达比它需要的更复杂,特别是在不必要地涉及三元运算符时.以下表达式计算所有输入的相同结果,而不涉及三元运算符.* 它是替代品的理想选择,但与任何优化问题一样,测试时必须:

const int32_t value = (int32_t)(inst & 0x1FFFF) - (int32_t)(inst & 0x20000);
Run Code Online (Sandbox Code Playgroud)

或者@yynax对类似行的建议的这种变化可能更适合优化器:

const int32_t value = (int32_t)(inst & 0x3FFFF ^ 0x20000) - (int32_t)0x20000;
Run Code Online (Sandbox Code Playgroud)

在每种情况下,强制转换都避免了实现定义的行为; 在许多架构上,就机器代码而言,它们将是无操作的.在这些体系结构中,这些表达式在所有情况下都比在您的情况下涉及更少的操作,更不用说是无条件的.

涉及转移的竞争性替代方案也可以很好地优化,但是所有这些替代方案必然依赖于实现定义的行为,因为左移的整数溢出,负整数是右移的左手操作数,和/或转换为输出范围值到有符号整数类型.您必须自己确定是否构成问题.

* 由GCC 4.4.7针对x86_64编译.原始表达式为某些输入调用实现定义的行为,因此在其他实现中,这两个表达式可能会为这些输入计算不同的值.