This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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.
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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]