Bug 28484

Summary: [F03] system_clock with real-type count_rate does not compile
Product: gcc Reporter: tobias.burnus
Component: fortranAssignee: Francois-Xavier Coudert <fxcoudert>
Status: RESOLVED FIXED    
Severity: normal CC: fxcoudert, gcc-bugs, janus, jb, kargls
Priority: P3 Keywords: rejects-valid
Version: 4.2.0   
Target Milestone: 5.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2007-05-29 20:44:46
Bug Depends on:    
Bug Blocks: 20585    
Attachments: Idea how libgfortran/intrinsic/system_clock.c could look like
Revised idea how libgfortran/intrinsic/system_clock.c could look like

Description tobias.burnus 2006-07-25 17:09:10 UTC
When compiling the following program,
------------------
  real :: cntrate
  call system_clock(count_rate=cntrate)
end
------------------
gfortran (4.2.0 20060725) shows the error:

  call system_clock(count_rate=cntrate)
                              1
Error: 'count_rate' argument of 'system_clock' intrinsic at (1) must be INTEGER

Expected: No error is shown as the Fortran standard (quoting from Fortran 2003) allows this:

--------------------------------
13.7.117 SYSTEM_CLOCK ([COUNT, COUNT_RATE, COUNT_MAX])

Arguments.
COUNT  (optional)   shall be scalar and of type integer.
COUNT RATE (optional)  shall be scalar and of type integer or real.
COUNT MAX (optional) shall be scalar and of type integer.
--------------------------------
Comment 1 kargls 2006-07-25 20:22:38 UTC
gfortran is primarily a Fortran 95 with a few Fortran 2003 enhancements.
Comment 2 Andrew Pinski 2006-09-03 06:10:52 UTC
Confirmed.
Comment 3 patchapp@dberlin.org 2006-10-28 16:39:26 UTC
Subject: Bug number PR28484

A patch for this bug has been added to the patch tracker.
The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-10/msg01387.html
Comment 4 Tobias Burnus 2006-10-28 22:13:07 UTC
Assign.

Preliminary patch at:
http://gcc.gnu.org/ml/gcc-patches/2006-10/msg01387.html
Comment 5 Tobias Burnus 2006-11-02 16:02:41 UTC
Created attachment 12535 [details]
Idea how libgfortran/intrinsic/system_clock.c could look like

Some bits of thought.

Methods obtaining the time:
* clock_gettime() [POSIX]
  10^-9s (nanosecond) resolution, options:
  CLOCK_REALTIME  - on unix time since the epoch [I would suggested this]
  CLOCK_MONOTONIC - survives even changing the time,
     but starting point is arbitrary
  See also PR 15516 for assembler calling sequences for Linux

* gettimeofday (&tv, NULL) [POSIX]
  10^-6s (microsecond) resolution

* time() [POSIX]
  second resolution


Resolution -> time able to be represented
---------------------------------------------
For huge(i4) = 2147483647
1000 ms:    68 years
 100 ms:  2485 days
  10 ms:   246 days
   1 ms:    25 days
 100 us:    60 hours
  10 us:     6 hours
=> 10 ms seems to be a good resolution, 25 days might be a bit short for some calculation jobs, but 250 days should be enough.

For huge(i8) = 9223372036854775807
1  s:      2e11 years
1 ms:      2e8  years
1 us: 292271    years
1 ns:    292    years
=> 1 ns seems to be ok

I'm thinking of the following library implementation:
Only do integer(8) as this seems to be enough. (See attachment.)

For iresolve.c one needs to do something like the following (pseudo code):

if(count != NULL && counts.type != 8)
  gfc_convert_type()
if(count != NULL && count_max.type != 8)
  gfc_convert_type()
if(count != NULL && count_rate.type != 8)
  gfc_convert_type()

c->resolved_sym = gfc_get_intrinsic_sub_symbol ("system_clock")

if (count != NULL && count.type == 4)
   count = (int4) ((count8/10000000) % GFC_INTEGER_4_HUGE)
else if (count != NULL && count.type != 8)
   count = (type) count8

if (count_rate != NULL && count_rate.type == 4)
   add_expression("if(count_rate8 == 0) count_rate = 0"
                  "else count_rate = 100")
else if (count != NULL && count.type != 8)
   count_rate = (type) count_rate8

if (count_max != NULL && count_max.type == 4)
   add_expression("if(count_max8 == 0) count_max = 0"
                  "else count_max = GFC_INTEGER_4_HUGE")
else if (count != NULL && count.type != 8)
   count_rate = (type) count_rate8
Comment 6 Tobias Burnus 2006-11-02 16:32:43 UTC
Created attachment 12536 [details]
Revised idea how libgfortran/intrinsic/system_clock.c could look like

The latter part is of cause not completely right if count_rate = 1 or 1000000, and for an error int16 and real counts didn't contain -huge().

Maybe having in the library a system_clock_4 version makes life easier.

The following pseudocode should then work with system_clock_4 and system_clock_8 (which has also the advantage that we don't modify the library which is nice in terms of compatibility :-)

if ( (counts != NULL && counts.type == 4)
   ||(count_max != NULL && count_max.type == 4) {
  if(count != NULL && counts.type != 4)
    gfc_convert_type()
  if(count != NULL && count_max.type != 4)
    gfc_convert_type()
  if(count != NULL && count_rate.type != 4)
    gfc_convert_type()

  c->resolved_sym = gfc_get_intrinsic_sub_symbol ("system_clock_4")

  if (counts != NULL && counts.type != 4)
    add_expression("if(counts4 < 0) counts = -huge_max(type)"
                   "else counts = (type) counts4")
  if (count_rate != NULL && count_rate.type != 4)
    count_rate = (type) count_rate4

  if (count_max != NULL && count_max.type != 4)
    count_rate = (type) count_rate4
} else {
  if(count != NULL && counts.type != 8)
    gfc_convert_type()
  if(count != NULL && count_max.type != 8)
    gfc_convert_type()
  if(count != NULL && count_rate.type != 8)
    gfc_convert_type()

  c->resolved_sym = gfc_get_intrinsic_sub_symbol ("system_clock_8")

  if (counts != NULL && counts.type != 8)
    add_expression("if(counts8 < 0) counts = -huge_max(type)"
                   "else counts = (type) counts8")
  if (count_rate != NULL && count_rate.type != 8)
    count_rate = (type) count_rate8

  if (count_max != NULL && count_max.type != 8)
    count_rate = (type) count_rate8
}

Now I only have to figure out how to add the conversion and the "if(counts8 < 0)" expression in iresolve.c.
Comment 7 Tobias Burnus 2007-05-22 16:16:25 UTC
Won't work on it for a while.
Comment 8 Daniel Franke 2007-05-29 20:44:46 UTC
Taking over.
Comment 9 Joost VandeVondele 2007-10-26 07:32:29 UTC
(In reply to comment #8)
> Taking over.
> 

Any news on this ?
Comment 10 Daniel Franke 2007-12-13 19:14:41 UTC
(In reply to comment #9)
> Any news on this ?

Bad ones. Lost track due to real-life interference. 
Unassigning myself for now.
Comment 11 Jerry DeLisle 2009-04-11 21:35:56 UTC
Raising this up a little since F2003 features are coming up
Comment 12 Janne Blomqvist 2009-12-19 10:50:11 UTC
Since the actual implementation of system_clock has no use for non-integer count rates, this should be implemented by creating an integer temporary in the frontend and then calling the existing functions.

Also, note that as of r155359 the integer(8) version of system_clock now provides microsecond resolution. In the future, this could be improved further by switching to using clock_gettime(CLOCK_MONOTONIC,...) which in addition to providing better resolution also gives a monotonic clock instead of a realtime clock that gettimeofday() gives.
Comment 13 Francois-Xavier Coudert 2014-06-15 16:59:25 UTC
Author: fxcoudert
Date: Sun Jun 15 16:58:53 2014
New Revision: 211686

URL: https://gcc.gnu.org/viewcvs?rev=211686&root=gcc&view=rev
Log:
	PR fortran/28484
	PR fortran/61429

	* check.c (gfc_check_system_clock): Improve checking of arguments.
	* intrinsic.texi: Update doc of SYSTEM_CLOCK.
	* iresolve.c (gfc_resolve_system_clock): Choose library function
	used depending on argument kinds.
	* trans-decl.c (gfc_build_intrinsic_function_decls): Build
	decls for system_clock_4 and system_clock_8.
	* trans-intrinsic.c (conv_intrinsic_system_clock): New function.
	(gfc_conv_intrinsic_subroutine): Call conv_intrinsic_system_clock.
	* trans.h (gfor_fndecl_system_clock4, gfor_fndecl_system_clock8):
	New variables.

	* gfortran.dg/system_clock_1.f90: New file.
	* gfortran.dg/system_clock_2.f90: New file.

Added:
    trunk/gcc/testsuite/gfortran.dg/system_clock_1.f90
    trunk/gcc/testsuite/gfortran.dg/system_clock_2.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/check.c
    trunk/gcc/fortran/intrinsic.texi
    trunk/gcc/fortran/iresolve.c
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog
Comment 14 Francois-Xavier Coudert 2014-06-15 17:02:09 UTC
Fixed on trunk (4.10).