标签: compiler-optimization

GCC如何优化循环内增加的未使用变量?

我写了这个简单的C程序:

int main() {
    int i;
    int count = 0;
    for(i = 0; i < 2000000000; i++){
        count = count + 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想看看gcc编译器如何优化这个循环(显然添加1 2000000000次应该是"一次添加2000000000 ").所以:

GCC test.c的,然后timea.out给出了:

real 0m7.717s  
user 0m7.710s  
sys 0m0.000s  
Run Code Online (Sandbox Code Playgroud)

$ gcc -O2 test.c 然后time ona.out`给出:

real 0m0.003s  
user 0m0.000s  
sys 0m0.000s  
Run Code Online (Sandbox Code Playgroud)

然后我用两个人拆开了gcc -S.第一个似乎很清楚:

    .file "test.c"  
    .text  
.globl main
    .type   main, @function  
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, …
Run Code Online (Sandbox Code Playgroud)

c gcc disassembly compiler-optimization

64
推荐指数
1
解决办法
7410
查看次数

编译器优化可能会导致整数溢出。可以吗?

我有一个int x。为简单起见,假设ints 占据范围 -2^31 到 2^31-1。我想计算2*x-1. 我允许x为任何值 0 <= x<= 2^30。如果我计算 2*(2^30),我会得到 2^31,这是整数溢出。

一种解决方案是计算2*(x-1)+1. 比我想要的多了一项减法,但这不应该溢出。但是,编译器会将其优化为2*x-1. 这是源代码的问题吗?这是可执行文件的问题吗?

是 Godbolt 的输出2*x-1

func(int):                               # @func(int)
        lea     eax, [rdi + rdi]
        dec     eax
        ret
Run Code Online (Sandbox Code Playgroud)

是 Godbolt 的输出2*(x-1)+1

func(int):                               # @func(int)
        lea     eax, [rdi + rdi]
        dec     eax
        ret
Run Code Online (Sandbox Code Playgroud)

c++ integer-overflow compiler-optimization undefined-behavior integer-arithmetic

64
推荐指数
4
解决办法
7744
查看次数

编译器可以从堆优化到堆栈分配吗?

就编译器优化而言,将堆分配更改为堆栈分配是否合法和/或可能?或者会破坏as-if规则

例如,假设这是代码的原始版本

{
    Foo* f = new Foo();
    f->do_something();
    delete f;
}
Run Code Online (Sandbox Code Playgroud)

编译器是否能够将此更改为以下内容

{
    Foo f{};
    f.do_something();
}
Run Code Online (Sandbox Code Playgroud)

我不这么认为,因为如果原始版本依赖于自定义分配器之类的东西,那将会产生影响.标准是否对此有具体说明?

c++ memory-management compiler-optimization language-lawyer

63
推荐指数
2
解决办法
3085
查看次数

为什么这个看似较慢的 C 循环实际上是其他方式的两倍?

我是一名 R 开发人员,使用 C 来实现算法目的,并且有一个问题:为什么看起来很慢的 C 循环实际上比其他方法更快。

在 R 中,我们的布尔类型实际上可以有三个值:truefalse和,并且我们在 C 级别na使用 an 来表示。int

我正在研究一个向量化&&操作(是的,我们已经在 R 中使用了这个,但请耐心等待),它也可以处理这种na情况。标量结果如下所示:

 F && F == F
 F && T == F
 F && N == F

 T && F == F
 T && T == T
 T && N == N

 N && F == F
 N && T == N
 N && N == N
Run Code Online (Sandbox Code Playgroud)

请注意,它的工作方式&&与 C 中类似,只不过当na与除 …

c performance clang compiler-optimization

61
推荐指数
4
解决办法
6884
查看次数

const在C/C++中提供了哪些优化?(如果有的话)

我知道在可能的情况下,在通过引用或指针传递参数时,应尽可能使用const关键字.如果我指定参数是常量,编译器可以做的任何优化吗?

可能有几种情况:

功能参数:

常量参考:

void foo(const SomeClass& obj)
Run Code Online (Sandbox Code Playgroud)

Constant SomeClass对象:

void foo(const SomeClass* pObj)
Run Code Online (Sandbox Code Playgroud)

并且指向SomeClass的常量指针:

void foo(SomeClass* const pObj)
Run Code Online (Sandbox Code Playgroud)

变量声明:

const int i = 1234
Run Code Online (Sandbox Code Playgroud)

函数声明:

const char* foo()
Run Code Online (Sandbox Code Playgroud)

每个提供什么样的编译器优化(如果有的话)?

c c++ const compiler-optimization

58
推荐指数
4
解决办法
2万
查看次数

超出-O3/-Ofast的G ++优化

问题

我们有一个用于模拟任务的中型程序,我们需要对其进行优化.我们已经尽最大努力优化我们的编程技能,包括使用GprofValgrind进行分析.

最后完成后,我们希望在几个系统上运行该程序可能已有几个月了.因此,我们真的很有兴趣将优化推向极限.

所有系统都将在相对较新的硬件(Intel i5或i7)上运行Debian/Linux.

问题

使用最新版本的g ++有哪些可能的优化选项,超出-O3/-Ofast?

我们也对昂贵的小优化感兴趣,从长远来看,这将是非常重要的.

我们现在用的是什么

现在我们使用以下g ++优化选项:

  • -Ofast:最高"标准"优化级别.包含-ffast-math在我们的计算中没有引起任何问题,因此我们决定采用它,尽管非标准符合性.
  • -march=native:启用所有CPU特定指令.
  • -flto 允许跨不同编译单元的链接时间优化.

c++ g++ compiler-optimization

57
推荐指数
4
解决办法
4万
查看次数

为什么Haskell中没有隐式并行性?

Haskell功能强大且纯粹,所以基本上它具有编译器能够处理隐式并行性所需的所有属性.

考虑这个简单的例子:

f = do
  a <- Just 1
  b <- Just $ Just 2
  -- ^ The above line does not utilize an `a` variable, so it can be safely
  -- executed in parallel with the preceding line
  c <- b
  -- ^ The above line references a `b` variable, so it can only be executed
  -- sequentially after it
  return (a, c)
  -- On the exit from a monad scope we wait for all computations to …
Run Code Online (Sandbox Code Playgroud)

parallel-processing concurrency haskell compiler-optimization

57
推荐指数
3
解决办法
4487
查看次数

当从未执行的代码被注释掉时,Java程序运行得更慢

我在一个Java程序中观察到了一些奇怪的行为.我试图尽可能地删除代码,同时仍然能够复制行为.代码全部如下.

public class StrangeBehaviour {

    static boolean recursionFlag = true;

    public static void main(String[] args) {
        long startTime = System.nanoTime();
        for (int i = 0; i < 10000; i ++) {
            functionA(6, 0);
        }
        long endTime = System.nanoTime();
        System.out.format("%.2f seconds elapsed.\n", (endTime - startTime) / 1000.0 / 1000 / 1000);
    }

    static boolean functionA(int recursionDepth, int recursionSwitch) {
        if (recursionDepth == 0) { return true; }
        return functionB(recursionDepth, recursionSwitch);
    }

    static boolean functionB(int recursionDepth, int recursionSwitch) {
        for (int i …
Run Code Online (Sandbox Code Playgroud)

java recursion compiler-optimization

57
推荐指数
3
解决办法
4365
查看次数

为什么没有一个主要编译器优化这个检查值是否已经设置的条件存储?

我偶然发现了这篇Reddit 帖子,它是对以下代码片段的一个玩笑,

void f(int& x) {
    if (x != 1) {
        x = 1;
    }
}
void g(int& x) {
    x = 1;
}
Run Code Online (Sandbox Code Playgroud)

说这两个函数不等同于“编译器”。我确信任何主要的 C++ 编译器都会将条件赋值优化为无条件存储,从而为f和发出相同的汇编代码g

然而,他们没有。

谁能向我解释为什么会这样?

我的想法是:无条件存储很可能会更快,因为无论如何我们都必须访问内存来读取比较值,并且分支代码会给分支预测器带来压力。此外,编译器不应将存储视为副作用(AFAIK),即使后续内存访问可能会更快或更慢,具体取决于是否f由于缓存局部性而采用分支。

那么编译器就无法弄清楚这一点吗?虽然证明f和 的等价性g可能并不容易,但我觉得这些编译器能够解决更困难的问题。那么我可能错了,这些功能毕竟不相等,或者这里发生了什么?

c++ micro-optimization compiler-optimization

56
推荐指数
3
解决办法
5926
查看次数

了解该规则,即“程序已按编写的方式执行”

我正在尝试理解常规规则。根据cppreference

as-if规则
允许进行任何和所有不改变程序可观察行为的代码转换

解释
只要满足以下条件,C ++编译器就可以对程序进行任何更改:[...]

我很难理解“说明”部分的第二个技巧:

2)在程序终止时,写入文件的数据与在执行程序时完全一样。

我只是不明白“程序是按书面形式执行”的意思。

c++ compiler-optimization

53
推荐指数
2
解决办法
2897
查看次数