繁体   English   中英

gcc内联asm语句被优化了-错误的约束?

[英]gcc inline asm statement gets optimized away - wrong constraints?

我在使用gcc内联asm语句时遇到问题; gcc似乎认为结果是一个常量(不是),并且优化了该语句。 认为我正确地使用了操作数约束,但想对此事发表第二意见。 如果问题不是我使用约束引起的,我将尝试隔离gcc错误报告的测试用例,但这可能很困难,因为即使周围代码中的细微更改也会导致问题消失。

有问题的嵌入式asm是

static inline void
ularith_div_2ul_ul_ul_r (unsigned long *r, unsigned long a1,
                 const unsigned long a2, const unsigned long b)
{
  ASSERT(a2 < b); /* Or there will be quotient overflow */
  __asm__(
            "# ularith_div_2ul_ul_ul_r: divq %0 %1 %2 %3\n\t"
            "divq %3"
            : "+a" (a1), "=d" (*r)
            : "1" (a2), "rm" (b)
            : "cc");
}

这是一个一字除数得到的两个字红利的相当一部分。 注意,输入“ a2”的高位字和其余输出“ * r”通过“ 1”约束与同一寄存器%rdx绑定。

从周围的代码中, ularith_div_2ul_ul_ul_r()被有效地调用,就像

if (s == 1)
  modpp[0].one = 0;
else
  ularith_div_2ul_ul_ul_r(&modpp[0].one, 0UL, 1UL, s);

因此输入的高位字a2为常数1UL。 gcc -S -fverbose_asm的结果asm输出如下所示:

(earlier:)
        xorl    %r8d, %r8d      # cstore.863
(then:)
        cmpq    $1, -208(%rbp)  #, %sfp
        movl    $1, %eax        #, tmp841
        movq    %rsi, -184(%rbp)        # prephitmp.966, MEM[(struct __modulusredcul_t *)&modpp][0].invm
        cmovne  -208(%rbp), %rcx        # prephitmp.966,, %sfp, prephitmp.966
        cmovne  %rax, %r8       # cstore.863,, tmp841, cstore.863
        movq    %r8, -176(%rbp) # cstore.863, MEM[(struct __modulusredcul_t *)&modpp][0].one

结果是,将ularith_div_2ul_ul_ul_r()调用的结果假定为常数1; divq永远不会出现在输出中。

各种变化使问题消失了。 不同的编译器标志,不同的代码上下文或标记asm块__asm__ __volatile__ (...) 然后,输出正确包含divq指令:

#APP
        # ularith_div_2ul_ul_ul_r: divq %rax %rdx %rdx -208(%rbp)       # a1, tmp590, tmp590, %sfp
        divq -208(%rbp) # %sfp
#NO_APP

因此,我对这里的内联装配人员提出的问题是:我对约束做错了什么吗?

该错误仅影响Ubuntu版本的gcc。 据我们所知,库存的GNU gcc不受影响。 该错误已报告给Ubuntu启动板并确认: Bug#1029454

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM