V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Panic
V2EX  ›  编程

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

  •  
  •   Panic · 2018-07-19 19:51:58 +08:00 · 2719 次点击
    这是一个创建于 2079 天前的主题,其中的信息可能已经有所发展或是发生改变。

    首先叙述下我的问题,编译器是 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 类型时这句话时这个与操作被编译器优化掉了,这个是正常的吗,还是我自己理解太浅了。。。

    请各位大神帮忙指点下

    第 1 条附言  ·  2018-07-20 08:35:01 +08:00
    (i & 0x1F) 其实是 (i & 0x0F), 这个是我后来调试改的,但问题还是上面描述的问题,f 对应的就是汇编里的 15
    3 条回复    2018-07-23 14:13:56 +08:00
    billlee
        1
    billlee  
       2018-07-19 22:56:03 +08:00   ❤️ 1
    不知道你这是什么架构。但我知道 x86 上的 shl, 本来就只会用 cl 中的低 5 位。所以 x86 的编译器开优化的时候一定会把那个 & 0x1f 优化掉。
    billlee
        2
    billlee  
       2018-07-19 23:20:07 +08:00   ❤️ 1
    不对,肯定还有哪里遇到 undefined behaviour 了

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

    这代码在 gcc -O0 下输出 0 1, -O1 下输出 0 0
    Panic
        3
    Panic  
    OP
       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
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   986 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:15 · PVG 04:15 · LAX 13:15 · JFK 16:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.