2016-02-25 20 views
0

讓我們考慮這個Fortran 95的一段代碼(假設它包含在一個名爲main.f95文件):gfortran如何處理無法訪問的代碼?

module params 
    implicit none 
    real*4, parameter :: r4_dum = 1 
    real, parameter :: r_dum = 1 
    logical, parameter :: r32bit = (kind(r4_dum)==kind(r_dum)) 
    contains 
     subroutine print_state 
      implicit none 
      print*,'r32bit: ', r32bit 
     end subroutine print_state 
end module 

module convert 
    contains 
     subroutine r32_to_64bit(r4, r8) 
      implicit none 
      real*4, intent(in) :: r4 
      real*8, intent(out) :: r8 
      r8 = dble(r4) 
     end subroutine r32_to_64bit 
end module convert 

program test 
    use params, only: r32bit, print_state 
    use convert, only: r32_to_64bit 
    implicit none 
    real :: myReal 
    real*8 :: work8 

    call print_state 
    if (r32bit) then 
     call r32_to_64bit(myReal, work8) 
    else 
     work8 = myReal 
    endif 
end program test 

正如你可以看到,在if (r32bit)else部分不可達。我跑了以下內容:

% gfortran -O3 -Wunreachable-code -fdump-tree-optimized main.f95 

,看是否gfortran發現無法訪問的一部分,並刪除無用的分支或沒有,但是這給一個拼命空輸出。看來gfortran不會在本例中撕掉代碼中不可到達的部分。

所以,我的問題是以下幾點:什麼是防止gfortran檢測到這個else部分是無用的,並擺脫它?

+0

@Adrien我不相信你的代碼「無法訪問」。這只是錯誤的,因爲錯誤指出,你的'真正的myReal'實際上是一個64位機器上的「真實(8)」。如果分支,編譯器不能(並且不應該)基於「無用」更改不正確的代碼。我想你可以很容易地想象如何徹底摧毀遺留的代碼庫重新編譯爲現代用途。 – NoseKnowsAll

+0

@NoseKnowsAll條件'if(r32bit)'使呼叫確實無法訪問。如果myReal是真實的(8)',感謝上述條件,這是沒有辦法的。我並不是要求編譯器糾正錯誤的調用,而是不會在永遠不會執行的調用中引發錯誤。 – Adrien

+0

@francescalus有道理。它解釋了爲什麼使用'-fdefault-real-8'選項編譯失敗。但是它並沒有解釋爲什麼當我沒有這個選項編譯時(在這種情況下代碼是有效的)沒有執行消除。 – Adrien

回答

2

我的編譯器(gfortran 4.7和5.3 -O3 -fdump-tree-optimized)完成了代碼消除:

main (integer(kind=4) argc, character(kind=1) * * argv) 
{ 
    static integer(kind=4) options.1[9] = {68, 1023, 0, 0, 1, 1, 0, 0, 31}; 

    <bb 2>: 
    _gfortran_set_args (argc_2(D), argv_3(D)); 
    _gfortran_set_options (9, &options.1[0]); 
    print_state(); 
    return 0; 

} 

並打印出正確的答案

> ./a.out 
r32bit: T 

你不能指望優化來解決無效可達代碼。即使無法訪問,代碼仍然無效。


當我添加一些診斷

if (r32bit) then 
    call r32_to_64bit(myReal, work8) 
    print *, '+' 
else 
    work8 = myReal 
    print *, '-' 
endif 

它仍然是正確的消除:

test() 
{ 
    struct __st_parameter_dt dt_parm.1; 

    <bb 2>: 
    print_state(); 
    dt_parm.1.common.filename = &"dead_elim.f90"[1]{lb: 1 sz: 1}; 
    dt_parm.1.common.line = 34; 
    dt_parm.1.common.flags = 128; 
    dt_parm.1.common.unit = 6; 
    _gfortran_st_write (&dt_parm.1); 
    _gfortran_transfer_character_write (&dt_parm.1, &"+"[1]{lb: 1 sz: 1}, 1); 
    _gfortran_st_write_done (&dt_parm.1); 
    dt_parm.1 ={v} {CLOBBER}; 
    return; 

} 

和程序的確打印+作爲其最後的輸出。

最終代碼沒有條件,它被淘汰。


也許你期望-fdump-tree-optimized立即打印一些東西?它沒有這樣做,它將優化的代碼寫入文件。在我的情況下,它被命名爲dead_elim.f90.191t.optimized

+0

我現在覺得自己像個白癡。我認爲'-fdump-tree-optimized'將它的輸出打印到標準輸出而不是文件中......我的結果和你一樣。謝謝。 – Adrien