https://gcc.gnu.org/g:b421a3b1a3809b0401a79ae8f4eac2ec0cca2e62

commit b421a3b1a3809b0401a79ae8f4eac2ec0cca2e62
Author: Thomas Koenig <tkoe...@gcc.gnu.org>
Date:   Fri Jul 26 19:46:48 2024 +0200

    Add compile-time version of selected_unsigned_kind.

Diff:
---
 gcc/fortran/arith.cc     | 23 +++++++++++++++++++++++
 gcc/fortran/check.cc     |  1 -
 gcc/fortran/expr.cc      |  1 -
 gcc/fortran/gfortran.h   |  1 +
 gcc/fortran/intrinsic.cc | 10 ++++++++++
 gcc/fortran/intrinsic.h  |  1 +
 gcc/fortran/simplify.cc  | 23 +++++++++++++++++++++++
 7 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/arith.cc b/gcc/fortran/arith.cc
index a7b8af7779d1..849fa784241d 100644
--- a/gcc/fortran/arith.cc
+++ b/gcc/fortran/arith.cc
@@ -160,6 +160,7 @@ void
 gfc_arith_init_1 (void)
 {
   gfc_integer_info *int_info;
+  gfc_unsigned_info *uint_info;
   gfc_real_info *real_info;
   mpfr_t a, b;
   int i;
@@ -202,6 +203,28 @@ gfc_arith_init_1 (void)
       int_info->range = (int) mpfr_get_si (a, GFC_RND_MODE);
     }
 
+  /* Similar, for UNSIGNED.  */
+  if (flag_unsigned)
+    {
+      for (uint_info = gfc_unsigned_kinds; uint_info->kind != 0; uint_info++)
+       {
+         /* Huge.  */
+         mpz_init (uint_info->huge);
+         mpz_set_ui (uint_info->huge, uint_info->radix);
+         mpz_pow_ui (uint_info->huge, uint_info->huge, uint_info->digits);
+
+         /* UNSIGNED is radix 2.  */
+         gcc_assert (uint_info->radix == 2);
+
+         /* Range.  */
+         mpfr_set_z (a, uint_info->huge, GFC_RND_MODE);
+         mpfr_log10 (a, a, GFC_RND_MODE);
+         mpfr_trunc (a,a);
+         uint_info->range = (int) mpfr_get_si (a, GFC_RND_MODE);
+       }
+
+    }
+
   mpfr_clear (a);
 
   for (real_info = gfc_real_kinds; real_info->kind != 0; real_info++)
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index e90a99df1e2b..25ae21a8e5f8 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -5012,7 +5012,6 @@ gfc_check_selected_int_kind (gfc_expr *r)
   return true;
 }
 
-
 bool
 gfc_check_selected_real_kind (gfc_expr *p, gfc_expr *r, gfc_expr *radix)
 {
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index 545a64dba239..b47a84ae1a93 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -700,7 +700,6 @@ gfc_extract_int (gfc_expr *expr, int *result, int 
report_error)
   return false;
 }
 
-
 /* Same as gfc_extract_int, but use a HWI.  */
 
 bool
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index f922bf3bb991..d7bbcf6cdcde 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -677,6 +677,7 @@ enum gfc_isym_id
   GFC_ISYM_STOPPED_IMAGES,
   GFC_ISYM_STORAGE_SIZE,
   GFC_ISYM_STRIDE,
+  GFC_ISYM_SU_KIND,
   GFC_ISYM_SUM,
   GFC_ISYM_SYMLINK,
   GFC_ISYM_SYMLNK,
diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index 40f4c4f4b0bc..9074fe3c186b 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -2952,6 +2952,16 @@ add_functions (void)
 
   make_generic ("selected_int_kind", GFC_ISYM_SI_KIND, GFC_STD_F95);
 
+  if (flag_unsigned)
+    {
+
+      add_sym_1 ("selected_unsigned_kind", GFC_ISYM_SU_KIND, 
CLASS_TRANSFORMATIONAL, ACTUAL_NO,
+                BT_INTEGER, di, GFC_STD_GNU, gfc_check_selected_int_kind,
+                gfc_simplify_selected_unsigned_kind, NULL, r, BT_INTEGER, di, 
REQUIRED);
+
+      make_generic ("selected_unsigned_kind", GFC_ISYM_SU_KIND, GFC_STD_GNU);
+    }
+
   add_sym_1 ("selected_logical_kind", GFC_ISYM_SL_KIND, 
CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_INTEGER, di,
             GFC_STD_F2023, /* it has the same requirements */ 
gfc_check_selected_int_kind,
             gfc_simplify_selected_logical_kind, NULL, r, BT_INTEGER, di, 
REQUIRED);
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index 2c287caa6ad5..bfd0ac4c7f01 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -399,6 +399,7 @@ gfc_expr *gfc_simplify_scale (gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_scan (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_selected_char_kind (gfc_expr *);
 gfc_expr *gfc_simplify_selected_int_kind (gfc_expr *);
+gfc_expr *gfc_simplify_selected_unsigned_kind (gfc_expr *);
 gfc_expr *gfc_simplify_selected_logical_kind (gfc_expr *);
 gfc_expr *gfc_simplify_selected_real_kind (gfc_expr *, gfc_expr *, gfc_expr *);
 gfc_expr *gfc_simplify_set_exponent (gfc_expr *, gfc_expr *);
diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index 18c9088ef667..b96f5ee713e3 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -7404,6 +7404,29 @@ gfc_simplify_selected_int_kind (gfc_expr *e)
   return gfc_get_int_expr (gfc_default_integer_kind, &e->where, kind);
 }
 
+/* Same as above, but with unsigneds.  */
+
+gfc_expr *
+gfc_simplify_selected_unsigned_kind (gfc_expr *e)
+{
+  int i, kind, range;
+
+  if (e->expr_type != EXPR_CONSTANT || gfc_extract_int (e, &range))
+    return NULL;
+
+  kind = INT_MAX;
+
+  for (i = 0; gfc_unsigned_kinds[i].kind != 0; i++)
+    if (gfc_unsigned_kinds[i].range >= range
+       && gfc_unsigned_kinds[i].kind < kind)
+      kind = gfc_unsigned_kinds[i].kind;
+
+  if (kind == INT_MAX)
+    kind = -1;
+
+  return gfc_get_int_expr (gfc_default_integer_kind, &e->where, kind);
+}
+
 
 gfc_expr *
 gfc_simplify_selected_logical_kind (gfc_expr *e)

Reply via email to