考虑一下简单的代码:
UINT64 result; UINT32 high,low; ... result = ((UINT64)high << 32) | (UINT64)low;
现代编译器会将其转换为真正的高位移位,还是将其优化为简单的副本到正确的位置?
如果没有,那么使用联合似乎比大多数人似乎使用的转变更有效.但是,让编译器优化它是理想的解决方案.
我想知道当他们需要额外的一点性能时我应该如何建议.
解决方法
我写了以下(希望有效)测试:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void func(uint64_t x);
int main(int argc,char **argv)
{
#ifdef UNION
union {
uint64_t full;
struct {
uint32_t low;
uint32_t high;
} p;
} result;
#define value result.full
#else
uint64_t result;
#define value result
#endif
uint32_t high,low;
if (argc < 3) return 0;
high = atoi(argv[1]);
low = atoi(argv[2]);
#ifdef UNION
result.p.high = high;
result.p.low = low;
#else
result = ((uint64_t) high << 32) | low;
#endif
// printf("%08x%08x\n",(uint32_t) (value >> 32),(uint32_t) (value & 0xffffffff));
func(value);
return 0;
}
运行gcc -s的未优化输出的差异:
< mov -4(%rbp),%eax < movq %rax,%rdx < salq $32,%rdx < mov -8(%rbp),%eax < orq %rdx,%rax < movq %rax,-16(%rbp) --- > movl -4(%rbp),%eax > movl %eax,-12(%rbp) > movl -8(%rbp),-16(%rbp)
我不知道集会,所以我很难对其进行分析.然而,看起来在非联合(顶级)版本上正如预期的那样发生了一些变化.
但是在启用优化-O2的情况下,输出是相同的.因此生成了相同的代码,两种方式都具有相同的性能.
(Linux / AMD64上的gcc版本4.5.2)
有或没有union的优化-O2代码的部分输出:
movq 8(%rsi),%rdi
movl $10,%edx
xorl %esi,%esi
call strtol
movq 16(%rbx),%rdi
movq %rax,%rbp
movl $10,%esi
call strtol
movq %rbp,%rdi
mov %eax,%eax
salq $32,%rdi
orq %rax,%rdi
call func
在if行生成的跳转之后,片段立即开始.