【问题标题】:clang infinite tail recursion optimizationclang 无限尾递归优化
【发布时间】:2017-03-31 08:07:30
【问题描述】:
#include <iostream> 

int foo(int i){ 
     return foo(i + 1);
} 

int main(int argc,char * argv[]){ 
     if(argc != 2){ 
         return 1; 
     } 
     std::cout << foo(std::atoi(argv[1])) << std::endl; 
} 

% clang++ -O2 test.cc

% 时间./a.out 42

1490723512

./a.out 42 0.00s user 0.00s system 69% cpu 0.004 total

% 时间./a.out 42

1564058296

./a.out 42 0.00s user 0.00s system 56% cpu 0.006 total

%g++ -O2 test.cc

% ./a.out 42 #infinte 递归

^C

% clang++ --version 
clang version 3.3 (tags/RELEASE_33/final) 
Target: x86_64-apple-darwin12.4.0 
Thread model: posix 
% g++ --version 
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) 
Copyright (C) 2007 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions.  There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

那么这是clang++的一个bug还是一个特性?

【问题讨论】:

    标签: c++ tail-recursion clang++


    【解决方案1】:

    虽然 g++ 和 clang++ 都能够编译 C++98 和 C++11 代码,但 clang++ 从一开始就被设计为 C++11 编译器,并且在其 DNA 中嵌入了一些 C++11 行为(因此说话)。

    在 C++11 中,C++ 标准开始支持线程,这意味着现在有一些特定的线程行为。特别是 1.10/24 状态:

    实现可能假设任何线程最终都会执行以下操作之一:

    ——终止,

    ——调用库 I/O 函数,

    ——访问或修改易失性对象,或

    ——执行同步操作或原子操作。

    [注意:这旨在允许编译器转换,例如删除空循环,即使无法证明终止。 ——尾注]

    而这正是 clang++ 在优化时所做的。它看到该函数没有副作用并删除它即使它没有终止。

    【讨论】:

    • Clang 再次击败 gcc
    猜你喜欢
    • 2021-11-18
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 2012-10-14
    • 2012-11-15
    • 2011-09-04
    相关资源
    最近更新 更多