在以下代码中没有"volatile"关键字时,编译器可以执行哪些优化?

gja*_*ain 5 c embedded volatile

以下是在运行Barrelfish操作系统时在Pandaboard上闪烁LED的一些代码.我的问题是,为什么不把LED的闪光灯,如果"挥发"关键字是从的定义中删除gpio_oegpio_dataout.

static volatile uint32_t *gpio_oe = (uint32_t *)(GPIO_BASE + 0x0134);
static volatile uint32_t *gpio_dataout = (uint32_t *)(GPIO_BASE + 0x013C);

void led_flash
{
    // Enable output
    *gpio_oe &= (~(1 << 8));

    // Toggle LED on and off till eternity
    while(true)
    {
      *gpio_dataout ^= (1 << 8);  // Set means LED on; Clear means LED off
       time_delay();  // To give blinking effect
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道如果变量的值可以通过程序外的源自发地改变,则需要使用volatile.但我在这里看不到这样的情况.编译器执行什么优化会使整个while循环闪烁LED无意义?这种优化背后的逻辑是什么,即.这种优化有意义的合法案例?

Ale*_*nze 9

您还需要volatile强制执行内存写入和生成代码访问volatile变量的顺序.对于常规变量,编译器可能会认为写入是不必要的,要么将它们丢弃,要么只保留最后一个.

从注释中移出:如果编译器看不到变量的读取,它可能根本不写任何内容,它甚至可以删除变量.

  • 如果编译器看不到变量的读取,它甚至可以删除变量. (3认同)

Cli*_*ord 5

至于编译器可以告诉,值*gpio_oe*gpio_dataout写入,但从来没有读过.对于普通数据存储器,这种访问模式完全是冗余的,因此可以进行优化.类似地,对于读取但从未写入的位置.

对于内存映射I/O,但是对"内存"位置的访问具有编译器不知道的副作用.声明位置volatile告诉编译器必须完全按照代码描述显式访问该位置.

除了内存映射I/O之外,在单独的线程(例如RTOS任务或中断处理程序)之间共享的内存也会出现类似的问题,因为语言同样没有意识到这些上下文.

Embedded.com涵盖了许多文章中的主题: