- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我刚刚测试了一个小例子来检查 __restrict__
是否在最新编译器的 C++ 中工作:
void foo(int x,int* __restrict__ ptr1, int& v2) {
for(int i=0;i<x;i++) {
if(*ptr1==v2) {
++ptr1;
} else {
*ptr1=*ptr1+1;
}
}
}
当使用最新的 gcc (gcc8.1 -O3 -std=c++14) 在 godbolt.org 上尝试时,__restrict__
按预期工作:v2
只加载一次,因为它不能使用 ptr1
别名。
这里是相关的装配部件:
.L5:
mov eax, DWORD PTR [rsi]
cmp eax, ecx # <-- ecx contains v2, no load from memory
jne .L3
add edx, 1
add rsi, 4
cmp edi, edx
jne .L5
现在与最新的 clang (clang 6.0.0 -O3 -std=c++14) 相同。它展开循环一次,因此生成的代码要大得多,但这里是要点:
.LBB0_3: # =>This Inner Loop Header: Depth=1
mov edi, dword ptr [rsi]
cmp edi, dword ptr [rdx] # <-- restrict didn't work, v2 loaded from memory in hot loop
jne .LBB0_9
add rsi, 4
mov edi, dword ptr [rsi]
cmp edi, dword ptr [rdx] # <-- restrict didn't work, v2 loaded from memory in hot loop
je .LBB0_12
为什么会这样?我知道 __restrict__
是非标准的,编译器可以随意忽略它,但它似乎是从代码中获得最后一点性能的非常基本的技术,所以我怀疑 clang在支持和忽略关键字本身的同时根本不支持它。那么,这里的问题是什么?我做错了什么吗?
最佳答案
这么多无用的评论...
这似乎是 Clang 别名分析器中的一个错误。如果您将 v2
的类型更改为 short
,编译器会根据基于类型的别名规则愉快地将其从循环中移除:
for.body: ; preds = %for.inc, %for.body.lr.ph
%i.09 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%ptr1.addr.08 = phi i32* [ %ptr1, %for.body.lr.ph ], [ %ptr1.addr.1, %for.inc ]
%1 = load i32, i32* %ptr1.addr.08, align 4, !tbaa !5
%cmp1 = icmp eq i32 %1, %conv
br i1 %cmp1, label %if.then, label %if.else
但是对于原始循环,您会为两个内存引用设置相同的别名,这就是中端无法优化它的原因:
%i.08 = phi i32 [ %inc, %for.inc ], [ 0, %for.body.preheader ]
%ptr1.addr.07 = phi i32* [ %ptr1.addr.1, %for.inc ], [ %ptr1, %for.body.preheader ]
%0 = load i32, i32* %ptr1.addr.07, align 4, !tbaa !1
%1 = load i32, i32* %v2, align 4, !tbaa !1
%cmp1 = icmp eq i32 %0, %1
br i1 %cmp1, label %if.then, label %if.else
请注意 !tbaa !1
附加到两个内存引用,这意味着编译器无法区分它们中的任何一个访问的内存。似乎 restrict
注解一路丢失了...
我鼓励您使用最新的 Clang 重现此内容并在 LLVM Bugzilla 中提交错误(一定要抄送 Hal Finkel)。
关于c++ - 为什么 clang 会忽略 __restrict__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50365141/
这个使用两个 __restrict__ int 数组的内核编译得很好: __global__ void kerFoo( int* __restrict__ arr0, int* __restrict_
我不太明白 __restrict__ 的概念CUDA 中的标记。 我用 __restrict__ 读过避免指针别名,特别是,如果指向的变量是只读的,则变量的读取得到优化,因为它被缓存了。 这是代码的简
我一直在看Mike Acton's talk on Data-oriented design in C++在 CppCon 2014 中,他给出了这个例子: int Foo::Bar(int coun
我刚刚测试了一个小例子来检查 __restrict__ 是否在最新编译器的 C++ 中工作: void foo(int x,int* __restrict__ ptr1, int& v2) {
这是一些相当简单的代码,使用 -O2 (gcc 4.8.5) 编译: unsigned char * linebuf; int yuyv_tojpegycbcr(unsigned char * bu
因为我的指针都指向非重叠内存,所以我全力以赴将传递给内核(及其内联函数)的指针替换为限制,并使它们也成为常量,只要有可能。然而,这增加了一些内核的寄存器使用,而减少了其他内核的使用。这对我来说没有多大
智能指针是下面的指针,那么有什么方法可以定义函数的 shared_ptr 参数而不是另一个 shared_ptr 或任何类型的另一个指针的别名? 或者出于某种原因,这是不必要的吗? 我关心 gcc >
我看到了一些关于它的帖子,但仍然不知道如何修复该错误。事情是这样的: char *data; char chat; snprintf(chat,"%d",getc(file)
这是我写的一些代码(使用 GCC 的 __restrict__ 扩展到 C++): #include using namespace std; int main(void) { int i
假设我有 struct s { int* __restrict__ p1; double v; }; void foo(int* __restrict__ p2, struct s m
char *local_buffer, *buff; fgets(buff, 1024, fp); local_buffer=strtok(buff,'\t'); //Error is coming
我是一名优秀的程序员,十分优秀!