Commit d0442491 by Harald Anlauf Committed by Harald Anlauf

re PR fortran/90577 (FAIL: gfortran.dg/lrshift_1.f90 with -O(2|3) and -flto)

2019-06-14  Harald Anlauf  <anlauf@gmx.de>

	PR fortran/90577
	PR fortran/90578
	* trans-intrinsic.c (gfc_conv_intrinsic_shift): Properly
	distinguish logical/arithmetic shifts.
	* intrinsic.texi: Update documentation for SHIFTR/SHIFTL/SHIFTA
	(Fortran 2008) and LSHIFT/RSHIFT (GNU extensions).

	PR fortran/90577
	PR fortran/90578
	* gfortran.dg/lrshift_1.f90: Adjust testcase.
	* gfortran.dg/shiftalr_3.f90: New testcase.

From-SVN: r272309
parent a8566e93
2019-06-14 Harald Anlauf <anlauf@gmx.de>
PR fortran/90577
PR fortran/90578
* trans-intrinsic.c (gfc_conv_intrinsic_shift): Properly
distinguish logical/arithmetic shifts.
* intrinsic.texi: Update documentation for SHIFTR/SHIFTL/SHIFTA
(Fortran 2008) and LSHIFT/RSHIFT (GNU extensions).
2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org> 2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/89646 PR fortran/89646
......
...@@ -9689,10 +9689,10 @@ The return value is a @code{INTEGER(4)} variable. ...@@ -9689,10 +9689,10 @@ The return value is a @code{INTEGER(4)} variable.
@table @asis @table @asis
@item @emph{Description}: @item @emph{Description}:
@code{LSHIFT} returns a value corresponding to @var{I} with all of the @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 bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined. nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
Bits shifted out from the left end are lost; zeros are shifted in from the result value is undefined. Bits shifted out from the left end are
the opposite end. lost; zeros are shifted in from the opposite end.
This function has been superseded by the @code{ISHFT} intrinsic, which This function has been superseded by the @code{ISHFT} intrinsic, which
is standard in Fortran 95 and later, and the @code{SHIFTL} intrinsic, is standard in Fortran 95 and later, and the @code{SHIFTL} intrinsic,
...@@ -12244,11 +12244,12 @@ The value returned is equal to ...@@ -12244,11 +12244,12 @@ The value returned is equal to
@table @asis @table @asis
@item @emph{Description}: @item @emph{Description}:
@code{RSHIFT} returns a value corresponding to @var{I} with all of the @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 bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined. nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
Bits shifted out from the right end are lost. The fill is arithmetic: the the result value is undefined. Bits shifted out from the right end
bits shifted in from the left end are equal to the leftmost bit, which in are lost. The fill is arithmetic: the bits shifted in from the left
two's complement representation is the sign bit. 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 This function has been superseded by the @code{SHIFTA} intrinsic, which
is standard in Fortran 2008 and later. is standard in Fortran 2008 and later.
...@@ -12783,11 +12784,12 @@ END PROGRAM ...@@ -12783,11 +12784,12 @@ END PROGRAM
@table @asis @table @asis
@item @emph{Description}: @item @emph{Description}:
@code{SHIFTA} returns a value corresponding to @var{I} with all of the @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 bits shifted right by @var{SHIFT} places. @var{SHIFT} that be
@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined. nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
Bits shifted out from the right end are lost. The fill is arithmetic: the the result value is undefined. Bits shifted out from the right end
bits shifted in from the left end are equal to the leftmost bit, which in are lost. The fill is arithmetic: the bits shifted in from the left
two's complement representation is the sign bit. end are equal to the leftmost bit, which in two's complement
representation is the sign bit.
@item @emph{Standard}: @item @emph{Standard}:
Fortran 2008 and later Fortran 2008 and later
...@@ -12823,10 +12825,10 @@ The return value is of type @code{INTEGER} and of the same kind as ...@@ -12823,10 +12825,10 @@ The return value is of type @code{INTEGER} and of the same kind as
@table @asis @table @asis
@item @emph{Description}: @item @emph{Description}:
@code{SHIFTL} returns a value corresponding to @var{I} with all of the @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 bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined. nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
Bits shifted out from the left end are lost, and bits shifted in from the result value is undefined. Bits shifted out from the left end are
the right end are set to 0. lost, and bits shifted in from the right end are set to 0.
@item @emph{Standard}: @item @emph{Standard}:
Fortran 2008 and later Fortran 2008 and later
...@@ -12862,10 +12864,10 @@ The return value is of type @code{INTEGER} and of the same kind as ...@@ -12862,10 +12864,10 @@ The return value is of type @code{INTEGER} and of the same kind as
@table @asis @table @asis
@item @emph{Description}: @item @emph{Description}:
@code{SHIFTR} returns a value corresponding to @var{I} with all of the @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 bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined. nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
Bits shifted out from the right end are lost, and bits shifted in from the result value is undefined. Bits shifted out from the right end
the left end are set to 0. are lost, and bits shifted in from the left end are set to 0.
@item @emph{Standard}: @item @emph{Standard}:
Fortran 2008 and later Fortran 2008 and later
......
...@@ -6346,6 +6346,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift, ...@@ -6346,6 +6346,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
bool arithmetic) bool arithmetic)
{ {
tree args[2], type, num_bits, cond; tree args[2], type, num_bits, cond;
tree bigshift;
gfc_conv_intrinsic_function_args (se, expr, args, 2); gfc_conv_intrinsic_function_args (se, expr, args, 2);
...@@ -6365,6 +6366,18 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift, ...@@ -6365,6 +6366,18 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
if (!arithmetic) if (!arithmetic)
se->expr = fold_convert (type, se->expr); 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 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
gcc requires a shift width < BIT_SIZE(I), so we have to catch this gcc requires a shift width < BIT_SIZE(I), so we have to catch this
special case. */ special case. */
...@@ -6373,7 +6386,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift, ...@@ -6373,7 +6386,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
args[1], num_bits); args[1], num_bits);
se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, 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)) /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
......
2019-06-14 Harald Anlauf <anlauf@gmx.de>
PR fortran/90577
PR fortran/90578
* gfortran.dg/lrshift_1.f90: Adjust testcase.
* gfortran.dg/shiftalr_3.f90: New testcase.
2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org> 2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/89646 PR fortran/89646
......
...@@ -10,7 +10,7 @@ program test_rshift_lshift ...@@ -10,7 +10,7 @@ program test_rshift_lshift
1, 2, 127, 128, 129, huge(i)/2, huge(i) /) 1, 2, 127, 128, 129, huge(i)/2, huge(i) /)
do n = 1, size(i) do n = 1, size(i)
do j = -30, 30 do j = 0, 31
if (lshift(i(n),j) /= c_lshift(i(n),j)) STOP 1 if (lshift(i(n),j) /= c_lshift(i(n),j)) STOP 1
if (rshift(i(n),j) /= c_rshift(i(n),j)) STOP 2 if (rshift(i(n),j) /= c_rshift(i(n),j)) STOP 2
end do end do
......
! { 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment