2012-07-20 74 views
2

我遇到了gcc內聯asm語句的問題;海灣合作委員會似乎認爲結果是一個常數(事實並非如此),並優化了聲明。我認爲我正確使用操作數約束,但想就此事發表第二意見。如果問題不在我使用的約束中,我會嘗試隔離gcc錯誤報告的測試用例,但這可能很困難,因爲即使周圍代碼的微妙變化也會導致問題消失。gcc inline 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 

所以,我的問題在這裏的內聯彙編的傢伙:我沒做錯事與約束上?

回答

1

該bug隻影響Ubuntu版本的gcc;據我們所知,GNU gcc的股票不受影響。該漏洞被報告給Ubuntu啓動板並確認:Bug #1029454