簡體   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