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
This commit is contained in:
Harald Anlauf 2019-06-14 18:41:20 +00:00 committed by Harald Anlauf
parent a8566e938c
commit d0442491d5
6 changed files with 97 additions and 24 deletions

View File

@ -1,3 +1,12 @@
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

View File

@ -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
@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
@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
@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
@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

View File

@ -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,
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,
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))

View File

@ -1,3 +1,10 @@
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

View File

@ -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

View File

@ -0,0 +1,42 @@
! { 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