aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2024-08-07 21:44:48 +0200
committerThomas Koenig <tkoenig@gcc.gnu.org>2024-08-07 21:44:48 +0200
commitd5c05281bacf79bca1c10c34135aa61e14be8acb (patch)
tree7b572f95ad4055b4d1fbb518ae6e1057e0c4fb5f
parent58cbd148ed210f33102dd04cfcb8cfb6d7d1dd76 (diff)
downloadgcc-d5c05281bacf79bca1c10c34135aa61e14be8acb.zip
gcc-d5c05281bacf79bca1c10c34135aa61e14be8acb.tar.gz
gcc-d5c05281bacf79bca1c10c34135aa61e14be8acb.tar.bz2
Min, MAX and ishft(c).
-rw-r--r--gcc/fortran/check.cc53
-rw-r--r--gcc/fortran/gfortran.texi2
-rw-r--r--gcc/fortran/simplify.cc20
-rw-r--r--gcc/testsuite/gfortran.dg/unsigned_11.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/unsigned_12.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/unsigned_13.f9018
6 files changed, 120 insertions, 14 deletions
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 54a84ae..108e05d 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -3472,8 +3472,18 @@ gfc_check_intconv (gfc_expr *x)
bool
gfc_check_ishft (gfc_expr *i, gfc_expr *shift)
{
- if (!type_check (i, 0, BT_INTEGER)
- || !type_check (shift, 1, BT_INTEGER))
+ if (flag_unsigned)
+ {
+ if (!type_check2 (i, 0, BT_INTEGER, BT_UNSIGNED))
+ return false;
+ }
+ else
+ {
+ if (!type_check (i, 0, BT_INTEGER))
+ return false;
+ }
+
+ if (!type_check (shift, 1, BT_INTEGER))
return false;
if (!less_than_bitsize1 ("I", i, NULL, shift, true))
@@ -3486,9 +3496,16 @@ gfc_check_ishft (gfc_expr *i, gfc_expr *shift)
bool
gfc_check_ishftc (gfc_expr *i, gfc_expr *shift, gfc_expr *size)
{
- if (!type_check (i, 0, BT_INTEGER)
- || !type_check (shift, 1, BT_INTEGER))
- return false;
+ if (flag_unsigned)
+ {
+ if (!type_check2 (i, 0, BT_INTEGER, BT_UNSIGNED))
+ return false;
+ }
+ else
+ {
+ if (!type_check (i, 0, BT_INTEGER))
+ return false;
+ }
if (size != NULL)
{
@@ -3962,11 +3979,29 @@ gfc_check_min_max (gfc_actual_arglist *arg)
gfc_current_intrinsic, &x->where))
return false;
}
- else if (x->ts.type != BT_INTEGER && x->ts.type != BT_REAL)
+ else
{
- gfc_error ("%<a1%> argument of %qs intrinsic at %L must be INTEGER, "
- "REAL or CHARACTER", gfc_current_intrinsic, &x->where);
- return false;
+ if (flag_unsigned)
+ {
+ if (x->ts.type != BT_INTEGER && x->ts.type != BT_REAL
+ && x->ts.type != BT_UNSIGNED)
+ {
+ gfc_error ("%<a1%> argument of %qs intrinsic at %L must be "
+ "INTEGER, REAL, CHARACTER or UNSIGNED",
+ gfc_current_intrinsic, &x->where);
+ return false;
+ }
+ }
+ else
+ {
+ if (x->ts.type != BT_INTEGER && x->ts.type != BT_REAL)
+ {
+ gfc_error ("%<a1%> argument of %qs intrinsic at %L must be "
+ "INTEGER, REAL or CHARACTER",
+ gfc_current_intrinsic, &x->where);
+ return false;
+ }
+ }
}
return check_rest (x->ts.type, x->ts.kind, arg);
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 1afd12f..aeb4fe9 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -2766,6 +2766,8 @@ As of now, the following intrinsics take unsigned arguments:
@item @code{BIT_SIZE}, @code{DIGITS} and @code{HUGE}
@item @code{DSHIFTL} and @code{DSHIFTR}
@item @code{IBCLR}, @code{IBITS} and @code{IBITS}
+@item @code{MIN} and @code{MAX}
+@item @code{ISHFT} and @code{ISHFTC}
@end itemize
This list will grow in the near future.
@c ---------------------------------------------------------------------
diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc
index b7b2807..0539603 100644
--- a/gcc/fortran/simplify.cc
+++ b/gcc/fortran/simplify.cc
@@ -3931,8 +3931,11 @@ simplify_shift (gfc_expr *e, gfc_expr *s, const char *name,
gfc_extract_int (s, &shift);
- k = gfc_validate_kind (BT_INTEGER, e->ts.kind, false);
- bitsize = gfc_integer_kinds[k].bit_size;
+ k = gfc_validate_kind (e->ts.type, e->ts.kind, false);
+ if (e->ts.type == BT_INTEGER)
+ bitsize = gfc_integer_kinds[k].bit_size;
+ else
+ bitsize = gfc_unsigned_kinds[k].bit_size;
result = gfc_get_constant_expr (e->ts.type, e->ts.kind, &e->where);
@@ -4008,7 +4011,11 @@ simplify_shift (gfc_expr *e, gfc_expr *s, const char *name,
}
}
- gfc_convert_mpz_to_signed (result->value.integer, bitsize);
+ if (result->ts.type == BT_INTEGER)
+ gfc_convert_mpz_to_signed (result->value.integer, bitsize);
+ else
+ gfc_reduce_unsigned(result);
+
free (bits);
return result;
@@ -4108,7 +4115,8 @@ gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz)
if (shift == 0)
return result;
- gfc_convert_mpz_to_unsigned (result->value.integer, isize);
+ if (result->ts.type == BT_INTEGER)
+ gfc_convert_mpz_to_unsigned (result->value.integer, isize);
bits = XCNEWVEC (int, ssize);
@@ -4154,7 +4162,8 @@ gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz)
}
}
- gfc_convert_mpz_to_signed (result->value.integer, isize);
+ if (result->ts.type == BT_INTEGER)
+ gfc_convert_mpz_to_signed (result->value.integer, isize);
free (bits);
return result;
@@ -5243,6 +5252,7 @@ min_max_choose (gfc_expr *arg, gfc_expr *extremum, int sign, bool back_val)
switch (arg->ts.type)
{
case BT_INTEGER:
+ case BT_UNSIGNED:
if (extremum->ts.kind < arg->ts.kind)
extremum->ts.kind = arg->ts.kind;
ret = mpz_cmp (arg->value.integer,
diff --git a/gcc/testsuite/gfortran.dg/unsigned_11.f90 b/gcc/testsuite/gfortran.dg/unsigned_11.f90
new file mode 100644
index 0000000..ad817a8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unsigned_11.f90
@@ -0,0 +1,23 @@
+! { dg-do run }
+! { dg-options "-funsigned" }
+! Test min/max
+program main
+ unsigned :: u_a, u_b
+ if (max(1u,2u) /= 2u) error stop 1
+ if (max(2u,1u) /= 2u) error stop 2
+ if (min(1u,2u) /= 1u) error stop 3
+ if (min(2u,1u) /= 1u) error stop 4
+ u_a = 1u
+ u_b = 2u
+ if (max(u_a,u_b) /= u_b) error stop 5
+ if (max(u_b,u_a) /= u_b) error stop 6
+ if (min(u_a,u_b) /= u_a) error stop 7
+ if (min(u_b,u_a) /= u_a) error stop 8
+ if (max(4294967295u, 1u) /= 4294967295u) error stop 9
+ u_a = 4294967295u
+ u_b = 1u
+ if (max(u_a,u_b) /= 4294967295u) error stop 10
+ if (max(u_b,u_a) /= 4294967295u) error stop 11
+ if (min(u_a,u_b) /= 1u) error stop 12
+ if (min(u_b,u_a) /= 1u) error stop 13
+end program
diff --git a/gcc/testsuite/gfortran.dg/unsigned_12.f90 b/gcc/testsuite/gfortran.dg/unsigned_12.f90
new file mode 100644
index 0000000..ecf8214
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unsigned_12.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+! { dg-options "-funsigned" }
+! Test some
+program main
+ unsigned :: u_a
+ u_a = 1u
+ if (ishft(1u,31) /= 2147483648u) stop 1
+ if (ishft(u_a,31) /= 2147483648u) stop 2
+
+ u_a = 3u
+ if (ishft(3u,2) /= 12u) stop 3
+ if (ishft(u_a,2) /= 12u) stop 4
+
+ u_a = huge(u_a)
+ if (ishftc(huge(u_a),1) /= huge(u_a)) stop 5
+ if (ishftc(u_a,1) /= u_a) stop 6
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/unsigned_13.f90 b/gcc/testsuite/gfortran.dg/unsigned_13.f90
new file mode 100644
index 0000000..79b0907
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unsigned_13.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+! { dg-options "-funsigned" }
+! Test basic functionality of ishft and ishftc.
+program main
+ unsigned :: u_a
+ u_a = 1u
+ if (ishft(1u,31) /= 2147483648u) stop 1
+ if (ishft(u_a,31) /= 2147483648u) stop 2
+
+ u_a = 3u
+ if (ishft(3u,2) /= 12u) stop 3
+ if (ishft(u_a,2) /= 12u) stop 4
+
+ u_a = huge(u_a)
+ if (ishftc(huge(u_a),1) /= huge(u_a)) stop 5
+ if (ishftc(u_a,1) /= u_a) stop 6
+
+end program