@table @asis
@item @emph{Description}:
@code{LSHIFT} returns a value corresponding to @var{I} with all of the
-bits shifted left by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the left end are lost; zeros are shifted in from
-the opposite end.
+bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the left end are
+lost; zeros are shifted in from the opposite end.
This function has been superseded by the @code{ISHFT} intrinsic, which
is standard in Fortran 95 and later, and the @code{SHIFTL} intrinsic,
@table @asis
@item @emph{Description}:
@code{RSHIFT} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost. The fill is arithmetic: the
-bits shifted in from the left end are equal to the leftmost bit, which in
-two's complement representation is the sign bit.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost. The fill is arithmetic: the bits shifted in from the left
+end are equal to the leftmost bit, which in two's complement
+representation is the sign bit.
This function has been superseded by the @code{SHIFTA} intrinsic, which
is standard in Fortran 2008 and later.
@table @asis
@item @emph{Description}:
@code{SHIFTA} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost. The fill is arithmetic: the
-bits shifted in from the left end are equal to the leftmost bit, which in
-two's complement representation is the sign bit.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} that be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost. The fill is arithmetic: the bits shifted in from the left
+end are equal to the leftmost bit, which in two's complement
+representation is the sign bit.
@item @emph{Standard}:
Fortran 2008 and later
@table @asis
@item @emph{Description}:
@code{SHIFTL} returns a value corresponding to @var{I} with all of the
-bits shifted left by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the left end are lost, and bits shifted in from
-the right end are set to 0.
+bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the left end are
+lost, and bits shifted in from the right end are set to 0.
@item @emph{Standard}:
Fortran 2008 and later
@table @asis
@item @emph{Description}:
@code{SHIFTR} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost, and bits shifted in from
-the left end are set to 0.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost, and bits shifted in from the left end are set to 0.
@item @emph{Standard}:
Fortran 2008 and later
bool arithmetic)
{
tree args[2], type, num_bits, cond;
+ tree bigshift;
gfc_conv_intrinsic_function_args (se, expr, args, 2);
if (!arithmetic)
se->expr = fold_convert (type, se->expr);
+ if (!arithmetic)
+ bigshift = build_int_cst (type, 0);
+ else
+ {
+ tree nonneg = fold_build2_loc (input_location, GE_EXPR,
+ logical_type_node, args[0],
+ build_int_cst (TREE_TYPE (args[0]), 0));
+ bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
+ build_int_cst (type, 0),
+ build_int_cst (type, -1));
+ }
+
/* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
gcc requires a shift width < BIT_SIZE(I), so we have to catch this
special case. */
args[1], num_bits);
se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
- build_int_cst (type, 0), se->expr);
+ bigshift, se->expr);
}
/* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
--- /dev/null
+! { dg-do run }
+!
+! Test shift intrinsics when the SHIFT argument equals BIT_SIZE(arg1).
+
+program test
+ implicit none
+ ! Test compile-time simplifications
+ if (ishft (-1, 32) /= 0) stop 1 ! 0 -> simplify_shift OK
+ if (ishft (-1,-32) /= 0) stop 2 ! 0 -> simplify_shift OK
+ if (shiftl (-1, 32) /= 0) stop 3 ! 0 -> simplify_shift OK
+ if (shiftr (-1, 32) /= 0) stop 4 ! 0 -> simplify_shift OK
+ if (shifta (-1, 32) /= -1) stop 5 ! -1 -> simplify_shift OK
+ if (rshift (-1, 32) /= -1) stop 6 ! -1 -> simplify_shift OK
+ if (lshift (-1, 32) /= 0) stop 7 ! 0 -> simplify_shift OK
+ ! Test run-time
+ call foo (-1)
+contains
+ subroutine foo (n)
+ integer(4) :: i, j, k, n
+ integer, parameter :: bb = bit_size (n)
+ ! Test code generated by gfc_conv_intrinsic_ishft
+ i = ishft (n, bb) ! Logical (left) shift (Fortran 2008)
+ j = ishft (n,-bb) ! Logical (right) shift (Fortran 2008)
+ if (i /= 0) stop 11
+ if (j /= 0) stop 12
+ ! Test code generated by gfc_conv_intrinsic_shift:
+ i = shiftl (n, bb) ! Logical left shift (Fortran 2008)
+ j = shiftr (n, bb) ! Logical right shift (Fortran 2008)
+ k = shifta (n, bb) ! Arithmetic right shift (Fortran 2008)
+ if (i /= 0) stop 13
+ if (j /= 0) stop 14
+ if (k /= -1) stop 15
+ i = lshift (n, bb) ! Logical left shift (GNU extension)
+ j = rshift (n, bb) ! Arithmetic right shift (GNU extension)
+ if (i /= 0) stop 16
+ if (j /= -1) stop 17
+ do i = bb-1,bb
+ if (shifta (n, i) /= -1) stop 18
+ if (rshift (n, i) /= -1) stop 19
+ end do
+ end subroutine foo
+end program test