首页 文章

在C中的std :: complex <double>和在gcc 6下的Fortran中的复杂* 16之间键入不匹配,并进行链接时优化

提问于
浏览
1

我使用一些科学计算代码从C调用Fortran例程,它突然开始在gcc 6下发出警告 . 这是准系统问题:

考虑在 mult.f90 中定义的Fortran子例程 mult

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 -5(版本5.4.1)替换g -6(我的版本是6.2.0)

  • 编译时没有 -flto 标志

  • 使用double(而不是std :: complex)和real * 8(而不是复数* 16)

我应该担心,还是这是一个我可以忽略的警告?在前一种情况下,我该如何解决这个问题?

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; 
      }
    }
    

    看结果:实现略有不同(fortran似乎不使用单个GP寄存器,而C使用RBX)但调用约定等完全相同,所以你不必担心

    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 ~ $
    

相关问题