请教下各位,这个是编译器优化是程序问题还是编译器的问题. 实在是想不出来

2018-07-19 19:51:58 +08:00
 Panic

首先叙述下我的问题,编译器是 64bit 编译器,主要代码如下:


#define _BIT(n) (((unsigned )(1)) << (n))

void  __write_icr(int idx, unsigned short value, int irq)
{
  printk("icr_dump %d %d %d %p %p %p\n", irq, idx, value, &idx, &value, &irq);
}

int main()
{
  for(int i = 1; i < 63; i++){
    __write_icr(i>>4, _BIT( (i & 0x1F) ), i);
  }
  
  return 0;
}

我省略了其他无关代码, 主要就是 main 函数里调用 __write_icr 函数。 注意 __write_icr 的第二个参数是 unsigned short 类型.

我提取了编译的中间文件,main 函数里的循环对应汇编如下:

.L31:
	add	x19, x19, 1
	cmp	x19, 2
	bne	.L33
	mov	w19, 1
	.loc 1 371 0
	mov	w20, w19

.L34:
	mov	w2, w19
	lsl	w1, w20, w19
	asr	w0, w19, 4
	bl	__write_icr
    
.LVL89:
	add	w19, w19, 1
	cmp	w19, 63
	bne	.L34
	mov	w0, 64

不知道为什么,(i & 0x1F) 这个操作被编译器忽略掉了, 导致后续传到 __write_icr 的数据不对。

但如果我吧 __write_icr 第二个类型修改为 unsigned int value, 编译出来就感觉是正确的。

    .L31:
	add	x19, x19, 1
	cmp	x19, 2
	bne	.L33
	mov	w19, 1
	.loc 1 371 0
	mov	w20, w19

.L34:
	and	w1, w19, 15
	mov	w2, w19
	lsl	w1, w20, w1
	asr	w0, w19, 4
	bl	__write_icr
.LVL89:
	add	w19, w19, 1
	cmp	w19, 63
	bne	.L34
	mov	w0, 64

其中会有这句 (and w1, w19, 15), 对应着 (i & 0x1F)。 试了很多次,原因就是使用 short 类型时这句话时这个与操作被编译器优化掉了,这个是正常的吗,还是我自己理解太浅了。。。

请各位大神帮忙指点下

2745 次点击
所在节点    编程
3 条回复
billlee
2018-07-19 22:56:03 +08:00
不知道你这是什么架构。但我知道 x86 上的 shl, 本来就只会用 cl 中的低 5 位。所以 x86 的编译器开优化的时候一定会把那个 & 0x1f 优化掉。
billlee
2018-07-19 23:20:07 +08:00
不对,肯定还有哪里遇到 undefined behaviour 了

https://gist.github.com/BillLeecn/846d96ec6a5f360d9b962e53a2acf56a

这代码在 gcc -O0 下输出 0 1, -O1 下输出 0 0
Panic
2018-07-23 14:13:56 +08:00
@billlee 谢了, 现在搞明白了, 确实是 编译器的 bug, 找了好几天最终定位了, 之前这里贴的应该没到定位点。
这个问题是 arm64 平台专用且遗留的问题, 在普通 gcc 和 arm 平台上都是没问题的。15 年就被修复了, 我这边厂家提供的编译器正好是有问题的。

对应的说明和 patch 在这里: https://gcc.gnu.org/bugzilla/show_bug.cgi?format=multiple&id=64304

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/472452

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX