diff mbox

[fortran] Bug 64432 - [5 Regression] SYSTEM_CLOCK(COUNT_RATE=rate) wrong result for integer(4)::rate

Message ID 550444BB.5070502@charter.net
State New
Headers show

Commit Message

Jerry DeLisle March 14, 2015, 2:24 p.m. UTC
Attachment on this one.

On 03/14/2015 07:22 AM, Jerry DeLisle wrote:
> On 03/08/2015 04:58 PM, Steve Kargl wrote:
>> On Mon, Mar 09, 2015 at 01:07:25AM +0200, Janne Blomqvist wrote:
>>> So I would prefer if we just hardcode the error values in the frontend
>>> (-HUGE, 0, 0), in case somebody tries to use the kind=1,2 versions,
>>> thus also removing the need for the new library functions, keeping the
>>> existing simpler ones instead. AFAICT this would be standards
>>> conforming. Any other opinions on this?
>>>
>
> Revised patch attached as requested. Regression tested on x86_64 linux. Typical
> results are shown below. I will provide a test case for the test-suite.
>
> $ ./a.out
> KIND=1: -127  0  0
> KIND=1: -127  0  0
> KIND=1: -127  .00000000  0
>   -----------------------------------------------------------
> KIND=2: -32767  0  0
> KIND=2: -32767  .00000000  0
>   -----------------------------------------------------------
> KIND=4: 57496123  1000  2147483647
> KIND=4: 57496123  1000.00000  2147483647
>   -----------------------------------------------------------
> KIND=8: 57496123484138  1000000000  9223372036854775807
> KIND=8: 57496123522116  1000000000.0000000  9223372036854775807
>   -----------------------------------------------------------
> KIND=10: 57496123575504  1000000000  9223372036854775807
> KIND=10: 57496123612377  1000000000.00000000000  9223372036854775807
>   -----------------------------------------------------------
> KIND=16: 57496123669210  1000000000  9223372036854775807
> KIND=16: 57496123698413  1000000000.00000000000000000000000000  9223372036854775807
>
>
> OK for trunk?
>
> Regards,
>
> Jerry
>
> 2015-03-14  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
>
>      PR fortran/64432
>      *trans-intrinisic.c (conv_intrinsic_system_clock): Check the
>      smallest kind passed in user arguments and hard-code results for
>      KIND=1 or KIND=2 to indicate no clock available.
>
> 2015-03-14 Jerry DeLisle  <jvdelisle@gcc.gnu.org>
>
>      PR libgfortran/64432
>      * intrinsics/system_clock.c (system_clock4, system_clock8):
>      Cleanup some whitespace.

Comments

Janne Blomqvist March 16, 2015, 12:07 p.m. UTC | #1
On Sat, Mar 14, 2015 at 4:24 PM, Jerry DeLisle <jvdelisle@charter.net> wrote:
> Attachment on this one.
>
>
> On 03/14/2015 07:22 AM, Jerry DeLisle wrote:
>>
>> On 03/08/2015 04:58 PM, Steve Kargl wrote:
>>>
>>> On Mon, Mar 09, 2015 at 01:07:25AM +0200, Janne Blomqvist wrote:
>>>>
>>>> So I would prefer if we just hardcode the error values in the frontend
>>>> (-HUGE, 0, 0), in case somebody tries to use the kind=1,2 versions,
>>>> thus also removing the need for the new library functions, keeping the
>>>> existing simpler ones instead. AFAICT this would be standards
>>>> conforming. Any other opinions on this?
>>>>
>>
>> Revised patch attached as requested. Regression tested on x86_64 linux.
>> Typical
>> results are shown below. I will provide a test case for the test-suite.
>>
>> $ ./a.out
>> KIND=1: -127  0  0
>> KIND=1: -127  0  0
>> KIND=1: -127  .00000000  0
>>   -----------------------------------------------------------
>> KIND=2: -32767  0  0
>> KIND=2: -32767  .00000000  0
>>   -----------------------------------------------------------
>> KIND=4: 57496123  1000  2147483647
>> KIND=4: 57496123  1000.00000  2147483647
>>   -----------------------------------------------------------
>> KIND=8: 57496123484138  1000000000  9223372036854775807
>> KIND=8: 57496123522116  1000000000.0000000  9223372036854775807
>>   -----------------------------------------------------------
>> KIND=10: 57496123575504  1000000000  9223372036854775807
>> KIND=10: 57496123612377  1000000000.00000000000  9223372036854775807
>>   -----------------------------------------------------------
>> KIND=16: 57496123669210  1000000000  9223372036854775807
>> KIND=16: 57496123698413  1000000000.00000000000000000000000000
>> 9223372036854775807
>>
>>
>> OK for trunk?
>>
>> Regards,
>>
>> Jerry
>>
>> 2015-03-14  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
>>
>>      PR fortran/64432
>>      *trans-intrinisic.c (conv_intrinsic_system_clock): Check the
>>      smallest kind passed in user arguments and hard-code results for
>>      KIND=1 or KIND=2 to indicate no clock available.
>>
>> 2015-03-14 Jerry DeLisle  <jvdelisle@gcc.gnu.org>
>>
>>      PR libgfortran/64432
>>      * intrinsics/system_clock.c (system_clock4, system_clock8):
>>      Cleanup some whitespace.

Thanks, this looks good. Ok for trunk.
diff mbox

Patch

Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c	(revision 221405)
+++ gcc/fortran/trans-intrinsic.c	(working copy)
@@ -2671,22 +2671,13 @@  conv_intrinsic_system_clock (gfc_code *code)
   stmtblock_t block;
   gfc_se count_se, count_rate_se, count_max_se;
   tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
-  tree type, tmp;
-  int kind;
+  tree tmp;
+  int least;
 
   gfc_expr *count = code->ext.actual->expr;
   gfc_expr *count_rate = code->ext.actual->next->expr;
   gfc_expr *count_max = code->ext.actual->next->next->expr;
 
-  /* The INTEGER(8) version has higher precision, it is used if both COUNT
-     and COUNT_MAX can hold 64-bit values, or are absent.  */
-  if ((!count || count->ts.kind >= 8)
-      && (!count_max || count_max->ts.kind >= 8))
-    kind = 8;
-  else
-    kind = gfc_default_integer_kind;
-  type = gfc_get_int_type (kind);
-
   /* Evaluate our arguments.  */
   if (count)
     {
@@ -2706,37 +2697,104 @@  conv_intrinsic_system_clock (gfc_code *code)
       gfc_conv_expr (&count_max_se, count_max);
     }
 
-  /* Prepare temporary variables if we need them.  */
-  if (count && count->ts.kind != kind)
-    arg1 = gfc_create_var (type, "count");
-  else if (count)
-    arg1 = count_se.expr;
+  /* Find the smallest kind found of the arguments.  */
+  least = 16;
+  least = (count && count->ts.kind < least) ? count->ts.kind : least;
+  least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
+						      : least;
+  least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
+						    : least;
 
-  if (count_rate && (count_rate->ts.kind != kind
-		     || count_rate->ts.type != BT_INTEGER))
-    arg2 = gfc_create_var (type, "count_rate");
-  else if (count_rate)
-    arg2 = count_rate_se.expr;
+  /* Prepare temporary variables.  */
 
-  if (count_max && count_max->ts.kind != kind)
-    arg3 = gfc_create_var (type, "count_max");
-  else if (count_max)
-    arg3 = count_max_se.expr;
+  if (count)
+    {
+      if (least >= 8)
+	arg1 = gfc_create_var (gfc_get_int_type (8), "count");
+      else if (least == 4)
+	arg1 = gfc_create_var (gfc_get_int_type (4), "count");
+      else if (count->ts.kind == 1)
+        arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
+				     count->ts.kind);
+      else
+        arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
+				     count->ts.kind);
+    }
 
+  if (count_rate)
+    {
+      if (least >= 8)
+	arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
+      else if (least == 4)
+	arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
+      else
+        arg2 = integer_zero_node;
+    }
+
+  if (count_max)
+    {
+      if (least >= 8)
+	arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
+      else if (least == 4)
+	arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
+      else
+        arg3 = integer_zero_node;
+    }
+
   /* Make the function call.  */
   gfc_init_block (&block);
-  tmp = build_call_expr_loc (input_location,
-			     kind == 4 ? gfor_fndecl_system_clock4
-				       : gfor_fndecl_system_clock8,
-                             3,
-			     arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
-				  : null_pointer_node,
-			     arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
-				  : null_pointer_node,
-			     arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
-				  : null_pointer_node);
-  gfc_add_expr_to_block (&block, tmp);
 
+if (least <= 2)
+  {
+    if (least == 1)
+      {
+	arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
+	       : null_pointer_node;
+	arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
+	       : null_pointer_node;
+	arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
+	       : null_pointer_node;
+      }
+  
+    if (least == 2)
+      {
+	arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
+	       : null_pointer_node;
+	arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
+	       : null_pointer_node;
+	arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
+	       : null_pointer_node;
+      }
+  }
+else
+  {
+    if (least == 4)
+      {
+	tmp = build_call_expr_loc (input_location,
+		gfor_fndecl_system_clock4, 3,
+		arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
+		       : null_pointer_node,
+		arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
+		       : null_pointer_node,
+		arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
+		       : null_pointer_node);
+	gfc_add_expr_to_block (&block, tmp);
+      }
+    /* Handle kind>=8, 10, or 16 arguments */
+    if (least >= 8)
+      {
+	tmp = build_call_expr_loc (input_location,
+		gfor_fndecl_system_clock8, 3,
+		arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
+		       : null_pointer_node,
+		arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
+		       : null_pointer_node,
+		arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
+		       : null_pointer_node);
+	gfc_add_expr_to_block (&block, tmp);
+      }
+  }
+
   /* And store values back if needed.  */
   if (arg1 && arg1 != count_se.expr)
     gfc_add_modify (&block, count_se.expr,
Index: libgfortran/intrinsics/system_clock.c
===================================================================
--- libgfortran/intrinsics/system_clock.c	(revision 221405)
+++ libgfortran/intrinsics/system_clock.c	(working copy)
@@ -109,10 +109,14 @@  gf_gettime_mono (time_t * secs, long * fracsecs, l
 
 #endif /* !__MINGW32 && !__CYGWIN__  */
 
-extern void system_clock_4 (GFC_INTEGER_4 *, GFC_INTEGER_4 *, GFC_INTEGER_4 *);
+extern void
+system_clock_4 (GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
+		GFC_INTEGER_4 *count_max);
 export_proto(system_clock_4);
 
-extern void system_clock_8 (GFC_INTEGER_8 *, GFC_INTEGER_8 *, GFC_INTEGER_8 *);
+extern void
+system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
+		GFC_INTEGER_8 *count_max);
 export_proto(system_clock_8);
 
 
@@ -122,10 +126,10 @@  export_proto(system_clock_8);
    for COUNT.  */
 
 void
-system_clock_4(GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
+system_clock_4 (GFC_INTEGER_4 *count, GFC_INTEGER_4 *count_rate,
 	       GFC_INTEGER_4 *count_max)
 {
-#if defined(__MINGW32__) || defined(__CYGWIN__) 
+#if defined(__MINGW32__) || defined(__CYGWIN__)
   if (count)
     {
       /* Use GetTickCount here as the resolution and range is
@@ -176,7 +180,7 @@  void
 
 void
 system_clock_8 (GFC_INTEGER_8 *count, GFC_INTEGER_8 *count_rate,
-		GFC_INTEGER_8 *count_max)
+		 GFC_INTEGER_8 *count_max)
 {
 #if defined(__MINGW32__) || defined(__CYGWIN__) 
   LARGE_INTEGER cnt;