1

C++ から Fortran ルーチンを呼び出す科学計算コードを使用していますが、gcc 6 で突然警告が表示されるようになりました。ベアボーンの問題は次のとおりです。

multで定義されている Fortran サブルーチンを考えてみましょうmult.f90

subroutine mult(c)
  complex*16 c
  c = c * c
  return
end

これを C++ ファイルから呼び出しますtest.cpp

#include <complex>
#include <iostream>

extern "C" void mult_(std::complex<double> *);

int main() {
  std::complex<double> z (1,0);
  mult_(&z);

  std::cout << z << "\n";
  return 0;
}

g++-6 を使用してファイルをコンパイルすると、次の警告が表示されます。

$ g++-6 -O3 -W -Wall test.cpp mult.f90 -flto -o test2

test.cpp:4:17: warning: type of ‘mult_’ does not match original declaration [-Wlto-type-mismatch]
 extern "C" void mult_(std::complex<double> *);
                 ^
mult.f90:1:1: note: ‘mult’ was previously declared here
 subroutine mult(c)
 ^
mult.f90:1:1: note: code may be misoptimized unless -fno-strict-aliasing is used

次のいずれかを行うと、警告は消えます。

  • g++-6 (私が持っているバージョンは 6.2.0) を g++-5 (バージョン 5.4.1) に置き換えます。
  • -fltoフラグなしでコンパイルする
  • double (std::complex の代わりに) と real*8 (complex*16 の代わりに) を使用します。

心配する必要がありますか、それとも無視できる警告ですか? 前者の場合、どうすれば問題を解決できますか?

4

1 に答える 1

1

私が見つけた最も近い関連の問題は https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78562#c6です

コンパイラの警告は関係ないようです。

次のコードを C++ でコンパイルし、生成されたアセンブラと fortran コードを比較しました。

extern "C" 
{
  void mult_(std::complex<double> *z)
  {
      *z = *z * *z; 
  }
}

結果を見る : 実装は若干異なりますが (C++ は RBX を使用するのに対し、Fortran は GP レジスタを 1 つも使用していないようです)、呼び出し規約などはまったく同じであるため、心配する必要はありません。

rep ~ $ g++ -S -O3 -Wall test2.cpp
rep ~ $ g++ -S -O3 mult.f90
rep ~ $ cat mult.s

-----------------------------Snip----------------------------

.LFB0:
        .cfi_startproc
        movsd   (%rdi), %xmm0
        movsd   8(%rdi), %xmm1
        movapd  %xmm0, %xmm2
        movapd  %xmm1, %xmm3
        mulsd   %xmm0, %xmm2
        mulsd   %xmm1, %xmm3
        mulsd   %xmm1, %xmm0
        subsd   %xmm3, %xmm2
        addsd   %xmm0, %xmm0
        movsd   %xmm2, (%rdi)
        movsd   %xmm0, 8(%rdi)
        ret
        .cfi_endproc

-----------------------------Snip----------------------------

rep ~ $ cat test2.s

-----------------------------Snip----------------------------

.LFB1991:
        .cfi_startproc
        movsd   8(%rdi), %xmm3
        pushq   %rbx
        .cfi_def_cfa_offset 16
        .cfi_offset 3, -16
        movsd   (%rdi), %xmm2
        movq    %rdi, %rbx
        movapd  %xmm3, %xmm1
        movapd  %xmm2, %xmm0
        call    __muldc3
        movsd   %xmm0, (%rbx)
        movsd   %xmm1, 8(%rbx)
        popq    %rbx
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc

-----------------------------Snip----------------------------
rep ~ $
于 2016-12-08T15:29:16.297 に答える