Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Incorrect reallocation of the LHS on assignment

MR
Beginner
925 Views

The attached code prints

$ ./test
 Before:            2
 After:            1 ; w =  0.6000000    

which is incorrect, since the shape of w should not change during the
assignment (no need for reallocation, and in any case the rhs has two
elements).

Notice that using w(:) solves the problem.

Compiled with
$ ifort test.f90 -o test
$ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 17.0.1.132 Build 20161005

program p
 implicit none

 integer, allocatable :: ii(:)
 real,    allocatable :: w(:), zz(:,:)

  allocate( ii , source=(/2,1/) )
  allocate( zz(2,2) , w(2) )

  zz(:,1) = 0.3
  zz(:,2) = 0.6

  write(*,*) "Before: ", shape(w)
  w = zz(1,ii)
  !w(:) = zz(1,ii) ! no problems here
  write(*,*) "After: ", shape(w), "; w =", w

end program p

 

0 Kudos
17 Replies
mecej4
Honored Contributor III
925 Views

There was a change in the default value of the -assume realloc_lhs option when the 2017 compiler came out. Please see https://software.intel.com/en-us/articles/intel-fortran-compiler-support-for-fortran-language-standards, where you can see (at almost the end) this notice:

NOTE: Compiler version 17.0 changed the default behavior to be that of /assume:realloc_lhs (-assume realloc_lhs). To disable that behavior in version 17.0 or later, use /assume:norealloc_lhs (-assume norealloc_lhs) or /nostandard-realloc-lhs (-nostandard-realloc-lhs)

0 Kudos
jimdempseyatthecove
Honored Contributor III
925 Views

mecej4,

Line 14 in #1 has

array = scalar

Why would array w get reallocated in this situation?

IOW, if line 14 were changed to

w = 1.0

Are you expecting w to be reallocated to an array of 1 element???

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
925 Views

This looks like a bug in Intel Fortran with the use of vector-subscript in the array assignment shown on line 14:

https://software.intel.com/en-us/node/678553

 

0 Kudos
Juergen_R_R
Valued Contributor I
925 Views

Actually, with gfortran 4.8.4 this gives an ICE. nagfor 6.1 is fine and gives array shape 2, as expected. ifort 16 also gives array shape 2, so this seems to be a regression in ifort 17. gfortran 7.0.0 also gives the expected 2 for the array shape, as well as PGI 16.10.

0 Kudos
mecej4
Honored Contributor III
925 Views

jimdempseyatthecove wrote:
 mecej4,

Line 14 in #1 has

     array = scalar

Why would array w get reallocated in this situation? 

Sorry, I did not make an analysis of the code. I simply remembered that there had been a recent change in the default behavior of IFort and brought that to the OP's attention.

0 Kudos
MR
Beginner
925 Views

mecej4 wrote:

Quote:

jimdempseyatthecove wrote:
 mecej4,

 

Line 14 in #1 has

     array = scalar

Why would array w get reallocated in this situation? 

 

Sorry, I did not make an analysis of the code. I simply remembered that there had been a recent change in the default behavior of IFort and brought that to the OP's attention.

At line 14, ii is an array, so this is indeed  array = array  (as noted by FortranFan in #4) and there is no need to reallocate the lhs. I think that this is a compiler bug in ifort 17.

0 Kudos
jimdempseyatthecove
Honored Contributor III
925 Views

oops, my bad, should have looked at the declaration of ii (it is an array not a scalar). You are right, this is (analogous to) a gather of zz. I should have read the code more closely. (bad habit of me using i, ii, iii as loop indices).

ii is a 1 dimensional array, z(1,ii) equivalent to z(1,[2,1]) produces a 1 dimensional array with two elements. w should not have been reallocated, however if it had been (due to the compiler not necessarily knowing the shape of ii) then it should have been reallocated into a 1 dimensional array with two elements.

Jim Dempsey

0 Kudos
MR
Beginner
925 Views

jimdempseyatthecove wrote:

oops, my bad, should have looked at the declaration of ii (it is an array not a scalar). You are right, this is (analogous to) a gather of zz. I should have read the code more closely. (bad habit of me using i, ii, iii as loop indices).

ii is a 1 dimensional array, z(1,ii) equivalent to z(1,[2,1]) produces a 1 dimensional array with two elements. w should not have been reallocated, however if it had been (due to the compiler not necessarily knowing the shape of ii) then it should have been reallocated into a 1 dimensional array with two elements.

Jim Dempsey

Indeed. Just one comment: given that the size of the lhs matches the rhs, reallocation is forbidden by the standard if I understand it correctly. This could be relevant in case the lhs is a TARGET, or in case it is has a derived type with a finalizer.

Marco

0 Kudos
Kevin_D_Intel
Employee
925 Views

Thank you for reporting this and for the concise reproducer. I escalated this to the Developers.

(Internal tracking id: DPD200417127)

0 Kudos
jimdempseyatthecove
Honored Contributor III
925 Views

>> Just one comment: given that the size of the lhs matches the rhs, reallocation is forbidden by the standard if I understand it correctly.

Various versions of the compiler generated code to do the reallocation regardless of the necessity, this may have been fixed. It wouldn't hurt to verify to assert if the (:) should be used or not. There was a similar issue with the unnecessary creation of a temporary array (this too may be fixed by now).

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
925 Views

Kevin D (Intel) wrote:

Thank you for reporting this and for the concise reproducer. I escalated this to the Developers.

(Internal tracking id: DPD200417127)

Kevin,

As noted by Juergen R. above, this would appear to be a regression in compiler 17, perhaps even update 1 (I didn't check initial release) since compiler 16, update 4 seems to work as expected.

Now, please note regression such as these are worrisome for users, it will be reassuring if Intel Fortran team were to share more on the regression testing and the QA procedure(s) followed for new compiler version updates.  You have to admit at some point bugs like these shouldn't get past beta-testing phase, let alone customer updates.

0 Kudos
Kevin_D_Intel
Employee
925 Views

Hi FortranFan – It does fail with the initial 17.0 release also. We have an extensive regression suite used to test the compilers and each test case we receive as a defect report is added to it. Our internal reporting system also has fields permitting us to tag reports as a regression and those are specifically watched and tracked. We really do try hard to avoid regressions and any defects in general because we do recognize how worrisome both of those are to customers. I can’t speak to the complete details of the testing since I don’t exercise it myself, but I am aware that Developer’s changes, development branches, and release candidates are tested extensively on a regular basis and at key points within our release cycle. It is impossible to test every possible feature combination and I expect that nothing representative like this case exists in our regression suite today otherwise it would have been seen earlier and addressed. We’ll know more about the root cause of this case once Development has investigated it further. If there’s something more that I can provide you regarding the testing to reassure you about that then please let me know.

0 Kudos
MR
Beginner
925 Views

Kevin, thank you for the feedback and the tracking ID.

Concerning comments #12 and #13, I would like to mention two more points:

1) the problem disappears if zz has rank one, i.e. w = zz(1,ii) does not work but w = zz_rank1(ii) works fine (I did not test different ranks). Without knowing the compiler internals, I can imagine that covering all the possible use cases for modern fortran is a formidable task for a test suite.

2) given 1), I think that the importance of updating-compilers, running unit-tests, reporting compiler-bugs is largely underestimated in the community of the fortran users.

Marco

0 Kudos
Kevin_D_Intel
Employee
925 Views

Thank you Marco, I will pass along those additional findings.

Development also just noted in the internal tracking report a relationship to vector-subscript (as FortranFan surmised) and that another workaround is to use -assume norealloc_lhs for this case.

0 Kudos
MR
Beginner
925 Views

Kevin D (Intel) wrote:

Development also just noted in the internal tracking report a relationship to vector-subscript (as FortranFan surmised)

Yes, sorry for not mentioning this explicitly in the first post. Indeed the test was rather mininal.

Kevin D (Intel) wrote:

and that another workaround is to use -assume norealloc_lhs for this case.

OK, thank you.

0 Kudos
FortranFan
Honored Contributor II
925 Views

Kevin D (Intel) wrote:

Hi FortranFan – .. We’ll know more about the root cause of this case once Development has investigated it further...

Kevin,

Thanks much for your feedback.  We look forward to further improvements in the upcoming updates this year and a real step up with respect to Fortran standard support in the next major release.

Re: "the root cause of this case", perhaps you can feed back to Intel Fortran Development there appears to be some connection to array element order in Fortran and thus the contiguous nature, or lack thereof, of the address in memory of the source data used with a vector subscript in an assignment.  Please see below a slightly modified example of the one in the original post and how the result is as expected for the case when source address is contiguous in memory:

program p

   implicit none

   integer, allocatable :: ii(:)
   real, allocatable :: zz(:,:)
   real, allocatable :: u(:)
   real, allocatable :: w(:)

   allocate( ii , source=[ 2,1 ] )
   allocate( zz(2,2), u(2), w(2) )

   zz(1,1) = 0.3
   zz(1,2) = 0.6
   zz(2,1) = 0.4
   zz(2,2) = 0.8

   write(*,*) "Before: shape(u) = ", shape(u)
   u = zz(ii,1)
   write(*,*) "After: shape(u) = ", shape(u), "; u =", u

   write(*,*) "Before: shape(w) = ", shape(w)
   w = zz(1,ii)
   write(*,*) "After: shape(w) = ", shape(w), "; w =", w

   stop

end program p

Upon execution with compiler 17, update 2:

 Before: shape(u) =  2
 After: shape(u) =  2 ; u = 0.4000000 0.3000000
 Before: shape(w) =  2
 After: shape(w) =  1 ; w = 0.6000000

 

0 Kudos
Kevin_D_Intel
Employee
925 Views

Thank you FortranFan for the added insight. I posted that in the internal tracking id.

0 Kudos
Reply