We are in the process of upgrading several hydrodynamics libraries from Intel® Parallel Studio XE 2015 with Visual Studio 2010 to the Intel Fortran Compiler that is part of the oneAPI with Visual Studio 2019.
We uncovered some weird behavior when compiling with /O2 optimizations. When copying data into a structure field, the result is mis-aligned and ends up in the wrong fields.
Here are the structures in question:
structure /coord_2d/ real north real east end structure structure /other_ships_structure/ character*120 object_id record /coord_2d/ position ! east, north position real heading ! degrees real length ! feet real beam ! feet real draft ! feet real displacement ! L.T. real forward_velocity ! ft/sec real transverse_velocity ! ft/sec real yaw_velocity ! deg/sec record /fender_input_structure / fender end structure
There is code that copies the data from one instance of this structure (ios -> data passed in from a C++ application that gathers the data) to another instance (ext -> internal data use in processing). Both ext.fndr.tships and ios.tships use the same structure.
ext.fndr.num_other_ships = ios.num_other_ships do i = 1, ext.fndr.num_other_ships ext.fndr.tships(i).object_id = ios.tships(i).object_id ext.fndr.tships(i).position.east = ios.tships(i).position.east ext.fndr.tships(i).position.north = ios.tships(i).position.north write(*,*) ext.fndr.tships(i).position.north, ext.fndr.tships(i).position.east, ext.fndr.tships(i).heading ext.fndr.tships(i).heading = ios.tships(i).heading ext.fndr.tships(i).length = ios.tships(i).length ext.fndr.tships(i).beam = ios.tships(i).beam
The write() command prints out the variables after position.east and position.north have been assigned. When compiled with /O2, the particular test has the following input:
ios.tships(i).position.east -> 94
ios.tships(i).position.north -> 1183
ext.fndr.tships(i).position.east -> 1183
ext.fndr.tships(i).position.north -> 0
ext.fndr.tships(i).heading -> 94
As you can see, the values get assigned essentially 4 bytes over, and end up in position.east and heading rather than in position.east and position.north.
If I compile this library optimizations disabled or with /O1, the assignment works correctly and the right values are in the fields.
Additionally, if I switch the call order (copy position.north first, and then position.east), it works correctly.
As you can imagine, this is a little unsettling and potentially indicative of other, currently hidden, assignment errors throughout our Fortran code base. Hopefully someone has an explanation that will allow us to fix this issue.