Несоответствие типов между std :: complex & lt; double & gt; в C ++ и сложных * 16 в Fortran под gcc 6 с оптимизацией по времени соединения

Я использую некоторый научный вычислительный код, который вызывает подпрограммы Фортрана из C ++, который внезапно начал выдавать предупреждение в gcc 6. Вот проблема barebones:

Рассмотрим подпрограмму Fortran mult определяется в 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)

Должен ли я быть обеспокоен, или это предупреждение, которое я могу игнорировать? В первом случае, как я могу решить проблему?

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]