[Bug fortran/33759] ICE in transfer_simplify_4.f90 at any level of optimization

fxcoudert at gcc dot gnu dot org gcc-bugzilla@gcc.gnu.org
Tue Mar 4 23:48:00 GMT 2008



------- Comment #13 from fxcoudert at gcc dot gnu dot org  2008-03-04 23:47 -------
It will probably be useless to others, who have already dug into this PR, but I
did have to research a bit to understand it, so I paste here the results of my
research... in case it can help.

-----------------------------------------
For the following reduced code:

  integer :: i
  i = 42
  print *, transfer(i, .true.)
  print *, transfer (transfer(i, .true.), 0)
  end

a.f90.013t.cfg has the (still valid):

  i.6 = i;
  transfer.4 = (logical(kind=4)) i.6;
  transfer.8 = transfer.4;
  D.876 = transfer.8;
  D.882 = D.876;
  transfer.5 = (integer(kind=4)) D.882;
  transfer.9 = transfer.5;
  D.878 = transfer.9;

a.f90.014t.cplxlower0 has made it into a pair of memcpy, but
a.f90.015t.veclower has them back in the form of two casts. a.f90.036t.dce1 has
them simplified into:

  transfer.4_9 = (logical(kind=4)) i_7;
  transfer.5_11 = (integer(kind=4)) transfer.4_9; 
  D.878 ={v} transfer.5_11;

a.f90.055t.copyrename2 still has that same form:

  transfer.4_9 = (logical(kind=4)) i_7;
  transfer.5_11 = (integer(kind=4)) transfer.4_9;
  D.878 = transfer.5_11;

but a.f90.056t.ccp2 definitely looses it:

  transfer.4_9 = 0;
  transfer.5_11 = 0;
  D.878 = 0;


So, the question is, is cpp2 right to change:

  i_7 = 42;
  transfer.4_9 = (logical(kind=4)) i_7;
  transfer.5_11 = (integer(kind=4)) transfer.4_9;
  D.878 = transfer.5_11;

into

  transfer.4_9 = 0;
  transfer.5_11 = 0;
  D.878 = 0;

I'm not sure what the semantics are for the logical kinds in the middle-end,
but it may be that only the least significant bit is used (if you change 42
into 43, you don't get the failure).

According to the related thread at
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/b29957a2f57fec25/27c2b4eca91c511f?lnk=gst&q=transfer+logical#27c2b4eca91c511f
correctly (comp.lang.fortran thread named "Transfer and variables that don't
use all their storage space.", started by... Tobias Burnus),
TRANSFER(TRANSFER(A,B),A) is legal and it's result should always be A (there
are some restrictions, but they are fulfilled in this precise case).
-----------------------------------------

Paul, to comment on your patch, it's not only integer and logical that are
concerned. You can do the same thing with logical and any other type, I'm
sure... and I'm even sure you could manage to do the same thing with a
real(kind=10), which has "unused bits" like a real type. (Or maybe, by playing
with NaN canonicalization, you could do it with any other floating-point type;
ie, choose an integer value that will TRANSFER into a given NaN, and the
middle-end might canonicalize this NaN or optimize it in sort weird way.) Also,
maybe the optimizer can sometimes be clever enough to see through your added
indirection level, can't it?

The only one way I see to do that would be to not create intermediate
variables. This is, after all, the meaning of the Fortran standard, that
although assignment can normalize (and array transfers are excluded from the
TRANSFER(TRANSFER(A,B),A) == A rule), scalar TRANSFERs without assignment don't
normalize. 


-- 

fxcoudert at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fxcoudert at gcc dot gnu dot
                   |                            |org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33759



More information about the Gcc-bugs mailing list