linux 编译 cflags,Linux 下如何绕过编译器优化

有同学在群里聊到编译器优化的事情,很多时候期望编译器默认做优化,但是有些场景是希望能绕过的,哪些呢?

这里举两个实实在在的例子。

第一个,在调试的时候,如果默认开启了优化,要关注的某个变量值,用 gdb 打印时可能会提示被优化掉了,会让人丈二和尚摸不着头脑。

第二个,就是某些场景,编译器并不理解背后的实际情况,比如说,连续往某个地址写两个值,编译器以为,这不是多此一举了,帮把最后一个写进去就好了,但是殊不知,这个地址可能是个硬件寄存器地址呢,写第一个,处理器调整一个状态,再写一个,再调整一个状态,两个都写完,才算完整,写不同的位有不同的含义。

怎么去掉显式优化参数

对于第一个,通常不太需要去改整个内核,比如说,把整个 -O2/-Os 都拿掉,这时可能引起的莫名情况比去 debug 某个问题可能还要棘手。所以,可以有针对性的,只对某个文件做优化参数调整即可。

这个本质上是拿掉 CFLAGS 里头的优化参数,其实用替换就好了,但是可选的用法有:

文件级:CFLAGS_REMOVE_xxx.o = -O2

arch/mips/kernel/Makefile:

ifdef CONFIG_FUNCTION_TRACER

CFLAGS_REMOVE_ftrace.o = -pg

CFLAGS_REMOVE_early_printk.o = -pg

CFLAGS_REMOVE_perf_event.o = -pg

CFLAGS_REMOVE_perf_event_mipsxx.o = -pg

endif

原理如下,就是从原始编译参数中 filter-out 掉特定参数:

$ grep CFLAGS_REMOVE -ur linux-stable/scripts/Makefile.lib

_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))

目录级:KBUILD_CFLAGS := $(filter-out -O2, $(KBUILD_CFLAGS))

arch/mips/boot/compressed/Makefile:

KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS))

自己主动 filter-out 掉。也可以直接调用脚本替换:

KBUILD_CFLAGS := $(shell echo $(KBUILD_CFLAGS) | sed -e "s/-pg//")

当然,用 Makefile 内置的 filter-out 效率会高,只是方便大家理解逻辑。

怎么确认这个编译参数是否真地生效呢,有两种方法:

一种是直接在相应 Makefile 打印 KBUILD_CFLAGS,例如:$(error $(KBUILD_CFLAGS)),另外一种是 make /path/to/xxx.o V=1 查看。在 Linux Lab 里头可以用 make k-x /path/to/xxx.o V=1。

除了直接拿掉,也可以考虑替换成 -Og,这个更适合调试需要。

怎么去掉隐式优化

第二个,也来看看实例:

drivers/cpufreq/loongson2_cpufreq.c:

static void loongson2_cpu_wait(void)

{

unsigned long flags;

u32 cpu_freq;

spin_lock_irqsave(&loongson2_wait_lock, flags);

cpu_freq = LOONGSON_CHIPCFG(0);

LOONGSON_CHIPCFG(0) &= ~0x7; /* Put CPU into wait mode */

LOONGSON_CHIPCFG(0) = cpu_freq; /* Restore CPU state */

spin_unlock_irqrestore(&loongson2_wait_lock, flags);

local_irq_enable();

}

上面中间三句,从 gcc 的角度来看,这不是傻嘛,啥也没做啊,又读又写是什么鬼,目标变量的值根本“没变”呢。原因是什么,这个背后的 LOONGSON_CHIPCFG(0) 是硬件寄存器地址,有它的时序意义,不同的位有不同的意义,写不同的值会有不同的动作。这个时候就得明确告诉 gcc:

arch/mips/include/asm/mach-loongson64/loongson.h:

#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))

这种情况怎么确认呢?make /path/to/xxx.s,看看代码还在不在。在 Linux Lab 里头可以用 make k-x /path/to/xxx.s。

送您一枚免费体验卡

更多 Linux 精彩欢迎透过下方免费体验卡访问『Linux 知识星球』:

79bc2b93cb93

Linux 知识星球免费体验卡

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值