re PR fortran/90577 (FAIL: gfortran.dg/lrshift_1.f90 with -O(2|3) and -flto)
authorHarald Anlauf <anlauf@gmx.de>
Fri, 14 Jun 2019 18:41:20 +0000 (18:41 +0000)
committerHarald Anlauf <anlauf@gcc.gnu.org>
Fri, 14 Jun 2019 18:41:20 +0000 (18:41 +0000)
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

gcc/fortran/ChangeLog
gcc/fortran/intrinsic.texi
gcc/fortran/trans-intrinsic.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/lrshift_1.f90
gcc/testsuite/gfortran.dg/shiftalr_3.f90 [new file with mode: 0644]

index 9a82b9b..def1810 100644 (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>
 
        PR fortran/89646
index f3f4c00..f390761 100644 (file)
@@ -9689,10 +9689,10 @@ The return value is a @code{INTEGER(4)} variable.
 @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,
@@ -12244,11 +12244,12 @@ The value returned is equal to
 @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.
@@ -12783,11 +12784,12 @@ END PROGRAM
 @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
@@ -12823,10 +12825,10 @@ The return value is of type @code{INTEGER} and of the same kind as
 @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
@@ -12862,10 +12864,10 @@ The return value is of type @code{INTEGER} and of the same kind as
 @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
index f6edd68..cc041f9 100644 (file)
@@ -6346,6 +6346,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
                          bool arithmetic)
 {
   tree args[2], type, num_bits, cond;
+  tree bigshift;
 
   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)
     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.  */
@@ -6373,7 +6386,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
                          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))
index 8ab6cb4..7332d53 100644 (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>
 
        PR fortran/89646
index b0e5379..d262921 100644 (file)
@@ -10,7 +10,7 @@ program test_rshift_lshift
          1, 2, 127, 128, 129, huge(i)/2, huge(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 (rshift(i(n),j) /= c_rshift(i(n),j)) STOP 2
     end do
diff --git a/gcc/testsuite/gfortran.dg/shiftalr_3.f90 b/gcc/testsuite/gfortran.dg/shiftalr_3.f90
new file mode 100644 (file)
index 0000000..4eb0ba7
--- /dev/null
@@ -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