Tag: 内置

为什么icc无法以合理的方式处理编译时分支提示?

开发人员可以使用__builtin_expect 内置来帮助编译器了解分支可能走向哪个方向。 在将来,我们可能会为此目的获得一个标准属性 ,但截至今天,至少所有clang , icc和gcc支持非标准的__builtin_expect 。 但是,当你使用它时, icc似乎会生成奇怪的代码1 。 也就是说,无论使用哪个方向进行预测,使用内置函数的代码都严格地比没有内置代码的代码更糟糕。 以下面的玩具function为例: int foo(int a, int b) { do { a *= 77; } while (b– > 0); return a * 77; } 在三个编译器中, icc是唯一一个将其编译为3个指令的最佳标量循环的编译器: foo(int, int): ..B1.2: # Preds ..B1.2 ..B1.1 imul edi, edi, 77 #4.6 dec esi #5.12 jns ..B1.2 # Prob 82% […]

__sync_val_compare_and_swap vs __sync_bool_compare_and_swap

我一直在考虑这两个函数的返回值。 __sync_bool_compare_and_swap函数的返回值似乎有明显的好处,即我可以用它来判断交换操作是否发生。 但是我看不到__sync_val_compare_and_swap的返回值。 首先,让我们有一个函数签名供参考(来自GCC docs减去var args): type __sync_val_compare_and_swap (type *ptr, type oldval type newval); 我看到的问题是__sync_val_compare_and_swap的返回值是* ptr的旧值。 确切地说,一旦适当的记忆障碍得以实施,这是该function的实施所看到的价值。 我明确说明了这一点,以满足在调用__sync_val_compare_and_swap和执行指令以强制执行内存屏障之间的事实,* ptr的值可能很容易改变。 现在,当函数返回该返回值时我能做什么? 尝试将它与* ptr进行比较是没有意义的,因为现在可以在其他线程上更改* ptr。 同样地比较newval和* ptr对我来说也没有什么帮助(除非我锁定* ptr,这可能首先破坏了我对primefaces的使用)。 所以我真正要做的就是询问返回值是否= = oldval,这是否有效(参见下面的警告)询问交换操作是否发生。 所以我本来可以使用__sync_bool_compare_and_swap。 我刚才提到的警告是,我在这里看到的唯一细微差别是,这样做并不能告诉我交换是否发生,它只是告诉我在内存屏障释放之前的某个时刻* ptr有相同的值为newval。 我正在考虑oldval == newval的可能性(虽然我很难看到一种有效实现函数的方法,以便它可以先检查这些值,如果它们是相同的则不交换,所以它可能是一个没有实际意义的点)。 但是我看不出这样一种情况,即知道这种差异会对我在呼叫站点产生影响。 事实上,我无法想象我会将oldval和newval设置为相等的情况。 我的问题是: 是否存在使用__sync_val_compare_and_swap和__sync_bool_compare_and_swap不等效的用例,即是否存在提供比另一个更多信息的情况? 在旁边 我之所以考虑这个问题,是因为我发现__sync_val_compare_and_swap的实现方式与sync_bool_compare_and_swap有竞争: inline int32_t __sync_val_compare_and_swap(volatile int32_t* ptr, int32_t oldval, int32_t newval) { int32_t ret = *ptr; […]

gcc中的“假设”条款

gcc(最新版本: __assume() )是否具有类似于icc所支持的__assume()内置的“assume”子句? 例如, __assume( n % 8 == 0 );

内部__lzcnt64使用不同的编译选项返回不同的值

我有以下代码: #include #include #include long long lzcnt(long long l) { return __lzcnt64(l); } int main(int argc, char** argv) { printf(“%lld\n”, lzcnt(atoll(argv[1]))); return 0; } 使用不同的编译器和选项运行(显示程序集): 铛 $ clang -Wall src/test.c -D__LZCNT__ && ./a.out 2047 53 0000000000400560 : 400560: 55 push %rbp 400561: 48 89 e5 mov %rsp,%rbp 400564: 48 89 7d f0 mov %rdi,-0x10(%rbp) 400568: […]

C / C ++:各种编译器/平台的内置类型的大小

我在哪里可以获得有关Mac OS X(32位和64位) gcc下的unsigned int编译大小的信息? 一般来说,我喜欢拥有一个可以使用编译器/设置/平台/类型的资源,并且能够查找该类型的大小。 有谁知道这样的事情? 更新:感谢所有回复。 我希望在某个地方有更多的东西,而不是我必须在每台机器上编写和运行的代码。

possible(x)和__builtin_expect((x),1)

我知道内核使用了likely , unlikely宏。 宏的文档位于内置函数:long __builtin_expect(long exp,long c) 。 但他们并没有真正讨论细节。 编译器究竟如何处理likely(x)和__builtin_expect((x),1) ? 它是由代码生成器还是优化器处理的? 它取决于优化级别吗? 代码生成的示例是什么?