Bug 36214

Summary: Wrong simplification of BOZ constants
Product: gcc Reporter: Francois-Xavier Coudert <fxcoudert>
Component: fortranAssignee: Daniel Kraft <domob>
Status: RESOLVED FIXED    
Severity: normal CC: d, gcc-bugs
Priority: P3 Keywords: wrong-code
Version: 4.4.0   
Target Milestone: 4.4.0   
Host: Target:
Build: Known to work:
Known to fail: 4.4.0 Last reconfirmed: 2008-09-10 14:54:45
Bug Depends on:    
Bug Blocks: 32834    

Description Francois-Xavier Coudert 2008-05-11 22:28:53 UTC
$ cat u.f90
   implicit none
   real, parameter :: r = transfer(0,0.)
   real(kind=8), parameter :: rd = dble(b'00000000000000000000000000000000&
                                         &01000000001010010101001111111101')

   if (cmplx(b'00000000000000000000000000000000&
              &01000000001010010101001111111101',0,8) /= rd) call abort

end
$ gfortran u.f90 && ./a.out 
Aborted


That's on x86_64-linux, and the weird thing is: if you remove the useless definition of r, it starts working again :)  And yet valgrind doesn't have anything to say. I'm mystified.

(PS: I found that one while investigating PR36186, but it's independent.)
Comment 1 Jerry DeLisle 2008-05-26 14:59:36 UTC
I am thinking that this may be the same bug as pr34828.  
Comment 2 Jerry DeLisle 2008-05-26 16:50:34 UTC
With valgrind at compile time on the test case: x86-64-linux-gnu

==5901== 158 bytes in 1 blocks are definitely lost in loss record 3 of 8
==5901==    at 0x4A04D1F: calloc (vg_replace_malloc.c:279)
==5901==    by 0xB4304A: xcalloc (xmalloc.c:162)
==5901==    by 0x55B877: init_emit (emit-rtl.c:5012)
==5901==    by 0x5F3E62: prepare_function_start (function.c:3906)
==5901==    by 0x5F5E98: init_function_start (function.c:3953)
==5901==    by 0x492BDD: trans_function_start (trans-decl.c:1618)
==5901==    by 0x499D6D: gfc_generate_function_code (trans-decl.c:3218)
==5901==    by 0x45570B: gfc_parse_file (parse.c:3585)
==5901==    by 0x47D81D: gfc_be_parse_file (f95-lang.c:258)
==5901==    by 0x6E49F1: toplev_main (toplev.c:965)
==5901==    by 0x3FF061E073: (below main) (libc-start.c:220)
==5901== 
Comment 3 Joost VandeVondele 2008-08-08 22:15:48 UTC
Maybe a hint from xlf90:

xlf90 test.f90
"test.f90", line 3.41: 1516-045 (E) Source is longer than target. Truncation will occur on the left.
"test.f90", line 6.14: 1516-045 (E) Source is longer than target. Truncation will occur on the left.

and xlf90 works code works fine.
Comment 4 Daniel Kraft 2008-09-10 14:54:45 UTC
I see the same problem with the program below:

implicit none
   real, parameter :: r = 0.0
   real(kind=8), parameter :: rd = real(b'00000000000000000000000000000000&
                                         &01000000001010010101001111111101', 8)

   if (real (b'00000000000000000000000000000000&
              &01000000001010010101001111111101', 8) /= rd) call abort
end

I'll try to investigate this interesting looking problem :P
Comment 5 kargls 2008-09-10 15:42:47 UTC
Daniel, 

I looked at this briefly last week.  Here's another test case that might be
easier to trace.  

   implicit none
   real(4) r
   real(8) rd
   complex(8) z
   rd =  dble(b'0000000000000000000000000000000001000000001010010101001111111101')
   z  = cmplx(b'0000000000000000000000000000000001000000001010010101001111111101',0,8)
   r = 0.
   if (z /= rd) call abort
   end

Of course, bugzilla has wrapped the long lines.

-fdump-parse-tree gives
      ASSIGN MAIN__:rd 5.31837115e-315_8
      ASSIGN MAIN__:z (complex 5.3183711317956924e-315_8 0_8)
      ASSIGN MAIN__:r 0
      IF (/= MAIN__:z __convert_r8_c8[[((MAIN__:rd))]])
        CALL _gfortran_abort ()
      ENDIF

I suspect that the conversion of the boz to the rd value is 
done with a kind=4 conversion rather than kind=8, but I haven't
been able to substantial my suspicions.
Comment 6 Daniel Kraft 2008-09-10 16:08:22 UTC
> -fdump-parse-tree gives
>       ASSIGN MAIN__:rd 5.31837115e-315_8
>       ASSIGN MAIN__:z (complex 5.3183711317956924e-315_8 0_8)
>       ASSIGN MAIN__:r 0
>       IF (/= MAIN__:z __convert_r8_c8[[((MAIN__:rd))]])
>         CALL _gfortran_abort ()
>       ENDIF
> 
> I suspect that the conversion of the boz to the rd value is 
> done with a kind=4 conversion rather than kind=8, but I haven't
> been able to substantial my suspicions.

That looks truely suspicious...  I'm currently waiting for the current trunk build to finish and will then investigate.  This part of the code will hopefully be another interesting learning experience :D
Comment 7 Daniel Kraft 2008-09-10 19:04:46 UTC
The problem is that gfc_interpret_float does not set the default mpfr precision to the value for its kind parameter but leaves the setting that is already present.  This is presumably the reason why inserting the dummy variable changed the test's behaviour, because this made caused the precision to be set to that for KIND=4 for the dummy variable.  Adding this initialization fixes the problem.

I will submit a patch shortly.
Comment 8 Daniel Kraft 2008-09-11 07:29:39 UTC
Subject: Bug 36214

Author: domob
Date: Thu Sep 11 07:28:18 2008
New Revision: 140264

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=140264
Log:
2008-09-11  Daniel Kraft  <d@domob.eu>

	PR fortran/36214
	* simplify.c (simplify_cmplx): Added linebreak to long line.
	* target-memory.c (gfc_convert_boz): Fix indentation.
	(gfc_interpret_float): Set mpfr precision to right value before
	calling mpfr_init.

2008-09-11  Daniel Kraft  <d@domob.eu>

	PR fortran/36214
	* gfortran.dg/boz_9.f90: Corrected test.
	* gfortran.dg/boz_13.f90: New test.
	* gfortran.dg/boz_14.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/boz_13.f90
    trunk/gcc/testsuite/gfortran.dg/boz_14.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/simplify.c
    trunk/gcc/fortran/target-memory.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/boz_9.f90

Comment 9 Daniel Kraft 2008-09-14 09:59:12 UTC
Subject: Bug 36214

Author: domob
Date: Sun Sep 14 09:57:50 2008
New Revision: 140358

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=140358
Log:
2008-09-11  Daniel Kraft  <d@domob.eu>

	PR fortran/36214
	* simplify.c (simplify_cmplx): Added linebreak to long line.
	* target-memory.c (gfc_convert_boz): Fix indentation.
	(gfc_interpret_float): Set mpfr precision to right value before
	calling mpfr_init.

2008-09-11  Daniel Kraft  <d@domob.eu>

	PR fortran/36214
	* gfortran.dg/boz_9.f90: Corrected test.
	* gfortran.dg/boz_11.f90: New test.
	* gfortran.dg/boz_12.f90: New test.

Added:
    branches/gcc-4_3-branch/gcc/testsuite/gfortran.dg/boz_11.f90
    branches/gcc-4_3-branch/gcc/testsuite/gfortran.dg/boz_12.f90
Modified:
    branches/gcc-4_3-branch/gcc/fortran/ChangeLog
    branches/gcc-4_3-branch/gcc/fortran/simplify.c
    branches/gcc-4_3-branch/gcc/fortran/target-memory.c
    branches/gcc-4_3-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_3-branch/gcc/testsuite/gfortran.dg/boz_9.f90

Comment 10 Daniel Kraft 2008-09-14 10:02:01 UTC
Fixed for trunk (4.4) and 4.3.