如何防止 GCC 优化繁忙的等待循环? [英] How to prevent GCC from optimizing out a busy wait loop?

查看:27
本文介绍了如何防止 GCC 优化繁忙的等待循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为 Atmel AVR 微控制器编写 C 代码固件.我将使用 GCC 编译它.另外,我想启用编译器优化(-Os-O2),因为我认为没有理由不启用它们,它们可能会更快地生成更好的汇编方式而不是手动编写程序集.

I want to write a C code firmware for Atmel AVR microcontrollers. I will compile it using GCC. Also, I want to enable compiler optimizations (-Os or -O2), as I see no reason to not enable them, and they will probably generate a better assembly way faster than writing assembly manually.

但我想要一小段未优化的代码.我想将函数的执行延迟一段时间,因此我想编写一个什么都不做的循环来浪费一些时间.无需精确,只需等待一段时间.

But I want a small piece of code not optimized. I want to delay the execution of a function by some time, and thus I wanted to write a do-nothing loop just to waste some time. No need to be precise, just wait some time.

/* How to NOT optimize this, while optimizing other code? */
unsigned char i, j;
j = 0;
while(--j) {
    i = 0;
    while(--i);
}

由于 AVR 中的内存访问要慢很多,我希望 ij 保存在 CPU 寄存器中.

Since memory access in AVR is a lot slower, I want i and j to be kept in CPU registers.

更新:我刚刚找到了 util/delay.hutil/delay_basic.h 来自 AVR Libc.尽管大多数时候使用这些函数可能是一个更好的主意,但这个问题仍然有效且有趣.

Update: I just found util/delay.h and util/delay_basic.h from AVR Libc. Although most times it might be a better idea to use those functions, this question remains valid and interesting.

相关问题:

推荐答案

我在访问 dmckee 的答案,但它采用的方法与他/她的答案不同.

I developed this answer after following a link from dmckee's answer, but it takes a different approach than his/her answer.

Function Attributes 来自 GCC 的文档提到:

Function Attributes documentation from GCC mentions:

noinline此函数属性可防止考虑内联函数.如果函数没有副作用,除了内联之外还有其他优化会导致函数调用被优化掉,尽管函数调用是实时的.为避免此类调用被优化掉,请将 asm ("");

noinline This function attribute prevents a function from being considered for inlining. If the function does not have side-effects, there are optimizations other than inlining that causes function calls to be optimized away, although the function call is live. To keep such calls from being optimized away, put asm ("");

这给了我一个有趣的想法......我没有在内部循环中添加 nop 指令,而是尝试在其中添加一个空的汇编代码,如下所示:

This gave me an interesting idea... Instead of adding a nop instruction at the inner loop, I tried adding an empty assembly code in there, like this:

unsigned char i, j;
j = 0;
while(--j) {
    i = 0;
    while(--i)
        asm("");
}

它奏效了!该循环没有被优化掉,也没有插入额外的 nop 指令.

And it worked! That loop has not been optimized-out, and no extra nop instructions were inserted.

更重要的是,如果你使用volatile,gcc会将这些变量存储在RAM中并添加一堆lddstd来复制它们到临时寄存器.另一方面,这种方法不使用 volatile 并且不会产生这样的开销.

What's more, if you use volatile, gcc will store those variables in RAM and add a bunch of ldd and std to copy them to temporary registers. This approach, on the other hand, doesn't use volatile and generates no such overhead.

更新: 如果您使用 -ansi-std 编译代码,则必须替换 asm带有 __asm__ 的关键字,如 在 GCC 文档中所述.

Update: If you are compiling code using -ansi or -std, you must replace the asm keyword with __asm__, as described in GCC documentation.

此外,如果您的 HOWTO.html#ss5.4" rel="noreferrer">汇编语句必须在我们放置它的地方执行,(即不能作为优化从循环中移出).

In addition, you can also use __asm__ __volatile__("") if your assembly statement must execute where we put it, (i.e. must not be moved out of a loop as an optimization).

这篇关于如何防止 GCC 优化繁忙的等待循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆