ndk和clang ++中的ARM编译器错误?

请考虑以下代码:

if 'Dec' == d:
    length_to_split.append(count)
    count = 0

很明显,回程丢失了。对于用于ARM处理器的clang和ndk编译器的这种情况,都会生成一个无限循环。拆卸后,很明显编译器会生成常规分支指令,而不是条件分支。

float test(int len,int* tab)
{
    for(int i = 0; i<len; i++)
        tab[i] = i;
}

有错误的示例可以在这里找到:https://godbolt.org/z/YDSFw-

请注意,c ++规范指出缺少返回值被视为未定义行为,但仅引用返回值。它不会影响上述说明。

我在这里错过了什么吗?有什么想法吗?

tanghui22222 回答:ndk和clang ++中的ARM编译器错误?

不,您无法以未定义的方式进行推理。

编译器可以自由使用未定义的行为及其周围的假设进行优化。编译器可以自由地假设您的代码将不包含未定义的行为。

在这种情况下,编译器可以假定不会访问具有未定义行为的代码。由于函数的结尾包含未定义的行为,因此编译器得出结论,实际上永远不会到达函数的结尾,因此可以优化循环。

如果删除-Oz并将-emit-llvm添加到编译器浏览器命令,则在不进行优化的情况下,您将看到LLVM IR clang最初产生的内容: https://godbolt.org/z/-dbeNj

define dso_local float @_Z4testiPi(i32 %0,i32* %1) #0 {
  %3 = alloca i32,align 4
  %4 = alloca i32*,align 4
  %5 = alloca i32,align 4
  store i32 %0,i32* %3,align 4
  store i32* %1,i32** %4,align 4
  store i32 0,i32* %5,align 4
  br label %6

6:                                                ; preds = %15,%2
  %7 = load i32,align 4
  %8 = load i32,align 4
  %9 = icmp slt i32 %7,%8
  br i1 %9,label %10,label %18

10:                                               ; preds = %6
  %11 = load i32,align 4
  %12 = load i32*,align 4
  %13 = load i32,align 4
  %14 = getelementptr inbounds i32,i32* %12,i32 %13
  store i32 %11,i32* %14,align 4
  br label %15

15:                                               ; preds = %10
  %16 = load i32,align 4
  %17 = add nsw i32 %16,1
  store i32 %17,align 4
  br label %6

18:                                               ; preds = %6
  call void @llvm.trap()
  unreachable
}

循环的结尾(标签18)包含unreachable。这可用于进一步优化,在循环开始时摆脱分支并进行比较。

编辑: 约翰·雷格(John Regehr)发表了excellent blog post,内容涉及如何推理C和C ++中未定义的行为。它有点长,但值得一读。

本文链接:https://www.f2er.com/3030068.html

大家都在问