[flang-commits] [flang] 72ac3e9 - [flang] Lower F08 shift intrinsics

Tarun Prabhu via flang-commits flang-commits at lists.llvm.org
Thu Jul 21 22:40:07 PDT 2022


Author: Tarun Prabhu
Date: 2022-07-21T23:36:08-06:00
New Revision: 72ac3e90da47d2b47a60b9fb04408d64e36efe53

URL: https://github.com/llvm/llvm-project/commit/72ac3e90da47d2b47a60b9fb04408d64e36efe53
DIFF: https://github.com/llvm/llvm-project/commit/72ac3e90da47d2b47a60b9fb04408d64e36efe53.diff

LOG: [flang] Lower F08 shift intrinsics

Lower F08 shift (shiftl, shiftr, shifta) and combined shift (dshiftl, dshiftr)
intrinsics. The combined shift intrinsics are implemented using the
definitions of shiftl and shiftr as described by the standard.

For non-conformant arguments to the shift intrinsics, the implementation tries
to replicate the behavior of other compilers if most of the other behave
consistently.

Differential Revision: https://reviews.llvm.org/D129316

Added: 
    flang/test/Lower/Intrinsics/dshiftl.f90
    flang/test/Lower/Intrinsics/dshiftr.f90
    flang/test/Lower/Intrinsics/shifta.f90
    flang/test/Lower/Intrinsics/shiftl.f90
    flang/test/Lower/Intrinsics/shiftr.f90

Modified: 
    flang/lib/Lower/IntrinsicCall.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index 7bdfe508511f..e5036a3daaa4 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -483,6 +483,8 @@ struct IntrinsicLibrary {
   fir::ExtendedValue genDotProduct(mlir::Type,
                                    llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genDprod(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  mlir::Value genDshiftl(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  mlir::Value genDshiftr(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genEoshift(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   void genExit(llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -543,6 +545,8 @@ struct IntrinsicLibrary {
   fir::ExtendedValue genScan(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genSetExponent(mlir::Type resultType,
                              llvm::ArrayRef<mlir::Value> args);
+  template <typename Shift>
+  mlir::Value genShift(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
   mlir::Value genSign(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genSpacing(mlir::Type resultType,
@@ -741,6 +745,8 @@ static constexpr IntrinsicHandler handlers[]{
      {{{"vector_a", asBox}, {"vector_b", asBox}}},
      /*isElemental=*/false},
     {"dprod", &I::genDprod},
+    {"dshiftl", &I::genDshiftl},
+    {"dshiftr", &I::genDshiftr},
     {"eoshift",
      &I::genEoshift,
      {{{"array", asBox},
@@ -910,6 +916,9 @@ static constexpr IntrinsicHandler handlers[]{
        {"kind", asValue}}},
      /*isElemental=*/true},
     {"set_exponent", &I::genSetExponent},
+    {"shifta", &I::genShift<mlir::arith::ShRSIOp>},
+    {"shiftl", &I::genShift<mlir::arith::ShLIOp>},
+    {"shiftr", &I::genShift<mlir::arith::ShRUIOp>},
     {"sign", &I::genSign},
     {"size",
      &I::genSize,
@@ -2664,6 +2673,54 @@ mlir::Value IntrinsicLibrary::genDprod(mlir::Type resultType,
   return builder.create<mlir::arith::MulFOp>(loc, a, b);
 }
 
+// DSHIFTL
+mlir::Value IntrinsicLibrary::genDshiftl(mlir::Type resultType,
+                                         llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 3);
+
+  mlir::Value i = args[0];
+  mlir::Value j = args[1];
+  mlir::Value shift = builder.createConvert(loc, resultType, args[2]);
+  mlir::Value bitSize = builder.createIntegerConstant(
+      loc, resultType, resultType.getIntOrFloatBitWidth());
+
+  // Per the standard, the value of DSHIFTL(I, J, SHIFT) is equal to
+  // IOR (SHIFTL(I, SHIFT), SHIFTR(J, BIT_SIZE(J) - SHIFT))
+  mlir::Value 
diff  = builder.create<mlir::arith::SubIOp>(loc, bitSize, shift);
+
+  mlir::Value lArgs[2]{i, shift};
+  mlir::Value lft = genShift<mlir::arith::ShLIOp>(resultType, lArgs);
+
+  mlir::Value rArgs[2]{j, 
diff };
+  mlir::Value rgt = genShift<mlir::arith::ShRUIOp>(resultType, rArgs);
+
+  return builder.create<mlir::arith::OrIOp>(loc, lft, rgt);
+}
+
+// DSHIFTR
+mlir::Value IntrinsicLibrary::genDshiftr(mlir::Type resultType,
+                                         llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 3);
+
+  mlir::Value i = args[0];
+  mlir::Value j = args[1];
+  mlir::Value shift = builder.createConvert(loc, resultType, args[2]);
+  mlir::Value bitSize = builder.createIntegerConstant(
+      loc, resultType, resultType.getIntOrFloatBitWidth());
+
+  // Per the standard, the value of DSHIFTR(I, J, SHIFT) is equal to
+  // IOR (SHIFTL(I, BIT_SIZE(I) - SHIFT), SHIFTR(J, SHIFT))
+  mlir::Value 
diff  = builder.create<mlir::arith::SubIOp>(loc, bitSize, shift);
+
+  mlir::Value lArgs[2]{i, 
diff };
+  mlir::Value lft = genShift<mlir::arith::ShLIOp>(resultType, lArgs);
+
+  mlir::Value rArgs[2]{j, shift};
+  mlir::Value rgt = genShift<mlir::arith::ShRUIOp>(resultType, rArgs);
+
+  return builder.create<mlir::arith::OrIOp>(loc, lft, rgt);
+}
+
 // EOSHIFT
 fir::ExtendedValue
 IntrinsicLibrary::genEoshift(mlir::Type resultType,
@@ -3755,6 +3812,32 @@ mlir::Value IntrinsicLibrary::genSetExponent(mlir::Type resultType,
                                    fir::getBase(args[1])));
 }
 
+// SHIFTA, SHIFTL, SHIFTR
+template <typename Shift>
+mlir::Value IntrinsicLibrary::genShift(mlir::Type resultType,
+                                       llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 2);
+
+  // If SHIFT < 0 or SHIFT >= BIT_SIZE(I), return 0. This is not required by
+  // the standard. However, several other compilers behave this way, so try and
+  // maintain compatibility with them to an extent.
+
+  unsigned bits = resultType.getIntOrFloatBitWidth();
+  mlir::Value bitSize = builder.createIntegerConstant(loc, resultType, bits);
+  mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0);
+  mlir::Value shift = builder.createConvert(loc, resultType, args[1]);
+
+  mlir::Value tooSmall = builder.create<mlir::arith::CmpIOp>(
+      loc, mlir::arith::CmpIPredicate::slt, shift, zero);
+  mlir::Value tooLarge = builder.create<mlir::arith::CmpIOp>(
+      loc, mlir::arith::CmpIPredicate::sge, shift, bitSize);
+  mlir::Value outOfBounds =
+      builder.create<mlir::arith::OrIOp>(loc, tooSmall, tooLarge);
+
+  mlir::Value shifted = builder.create<Shift>(loc, args[0], shift);
+  return builder.create<mlir::arith::SelectOp>(loc, outOfBounds, zero, shifted);
+}
+
 // SIGN
 mlir::Value IntrinsicLibrary::genSign(mlir::Type resultType,
                                       llvm::ArrayRef<mlir::Value> args) {

diff  --git a/flang/test/Lower/Intrinsics/dshiftl.f90 b/flang/test/Lower/Intrinsics/dshiftl.f90
new file mode 100644
index 000000000000..809bd83d03f8
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/dshiftl.f90
@@ -0,0 +1,156 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: dshiftl1_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i8>{{.*}}, %[[B:.*]]: !fir.ref<i8>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i8>{{.*}}
+subroutine dshiftl1_test(a, b, s, c)
+  integer(kind=1) :: a, b
+  integer :: s
+  integer(kind=1) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i8>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i8>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftl(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i8
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i8
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i8
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_L]] : i8
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_L]] : i8
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[S_CONV]] : i8
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i8
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i8
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_R]] : i8
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_R]] : i8
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[DIFF]] : i8
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i8
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i8
+end subroutine dshiftl1_test
+
+! CHECK-LABEL: dshiftl2_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i16>{{.*}}, %[[B:.*]]: !fir.ref<i16>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i16>{{.*}}
+subroutine dshiftl2_test(a, b, s, c)
+  integer(kind=2) :: a, b
+  integer :: s
+  integer(kind=2) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i16>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i16>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftl(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i16
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i16
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i16
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_L]] : i16
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_L]] : i16
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[S_CONV]] : i16
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i16
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i16
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_R]] : i16
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_R]] : i16
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[DIFF]] : i16
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i16
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i16
+end subroutine dshiftl2_test
+
+! CHECK-LABEL: dshiftl4_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i32>{{.*}}
+subroutine dshiftl4_test(a, b, s, c)
+  integer(kind=4) :: a, b
+  integer :: s
+  integer(kind=4) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftl(a, b, s)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_VAL]] : i32
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[S_VAL]], %[[C_0_L]] : i32
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[S_VAL]], %[[C_BITS_L]] : i32
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[S_VAL]] : i32
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i32
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_R]] : i32
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_R]] : i32
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[DIFF]] : i32
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i32
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i32
+end subroutine dshiftl4_test
+
+! CHECK-LABEL: dshiftl8_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i64>{{.*}}, %[[B:.*]]: !fir.ref<i64>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i64>{{.*}}
+subroutine dshiftl8_test(a, b, s, c)
+  integer(kind=8) :: a, b
+  integer :: s
+  integer(kind=8) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i64>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i64>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftl(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i64
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i64
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_L]] : i64
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_L]] : i64
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[S_CONV]] : i64
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i64
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_R]] : i64
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_R]] : i64
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[DIFF]] : i64
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i64
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i64
+end subroutine dshiftl8_test
+
+! CHECK-LABEL: dshiftl16_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i128>{{.*}}, %[[B:.*]]: !fir.ref<i128>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i128>{{.*}}
+subroutine dshiftl16_test(a, b, s, c)
+  integer(kind=16) :: a, b
+  integer :: s
+  integer(kind=16) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i128>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i128>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftl(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i128
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i128
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i128
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_L]] : i128
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_L]] : i128
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[S_CONV]] : i128
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i128
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i128
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_R]] : i128
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_R]] : i128
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[DIFF]] : i128
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i128
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i128
+end subroutine dshiftl16_test

diff  --git a/flang/test/Lower/Intrinsics/dshiftr.f90 b/flang/test/Lower/Intrinsics/dshiftr.f90
new file mode 100644
index 000000000000..565e142a4a06
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/dshiftr.f90
@@ -0,0 +1,156 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: dshiftr1_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i8>{{.*}}, %[[B:.*]]: !fir.ref<i8>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i8>{{.*}}
+subroutine dshiftr1_test(a, b, s, c)
+  integer(kind=1) :: a, b
+  integer :: s
+  integer(kind=1) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i8>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i8>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftr(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i8
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i8
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i8
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_L]] : i8
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_L]] : i8
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[DIFF]] : i8
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i8
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i8
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_R]] : i8
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_R]] : i8
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[S_CONV]] : i8
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i8
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i8
+end subroutine dshiftr1_test
+
+! CHECK-LABEL: dshiftr2_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i16>{{.*}}, %[[B:.*]]: !fir.ref<i16>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i16>{{.*}}
+subroutine dshiftr2_test(a, b, s, c)
+  integer(kind=2) :: a, b
+  integer :: s
+  integer(kind=2) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i16>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i16>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftr(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i16
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i16
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i16
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_L]] : i16
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_L]] : i16
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[DIFF]] : i16
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i16
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i16
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_R]] : i16
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_R]] : i16
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[S_CONV]] : i16
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i16
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i16
+end subroutine dshiftr2_test
+
+! CHECK-LABEL: dshiftr4_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i32>{{.*}}
+subroutine dshiftr4_test(a, b, s, c)
+  integer(kind=4) :: a, b
+  integer :: s
+  integer(kind=4) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftr(a, b, s)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_VAL]] : i32
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_L]] : i32
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_L]] : i32
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[DIFF]] : i32
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i32
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[S_VAL]], %[[C_0_R]] : i32
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[S_VAL]], %[[C_BITS_R]] : i32
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[S_VAL]] : i32
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i32
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i32
+end subroutine dshiftr4_test
+
+! CHECK-LABEL: dshiftr8_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i64>{{.*}}, %[[B:.*]]: !fir.ref<i64>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i64>{{.*}}
+subroutine dshiftr8_test(a, b, s, c)
+  integer(kind=8) :: a, b
+  integer :: s
+  integer(kind=8) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i64>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i64>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftr(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i64
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i64
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_L]] : i64
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_L]] : i64
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[DIFF]] : i64
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i64
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_R]] : i64
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_R]] : i64
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[S_CONV]] : i64
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i64
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i64
+end subroutine dshiftr8_test
+
+! CHECK-LABEL: dshiftr16_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i128>{{.*}}, %[[B:.*]]: !fir.ref<i128>{{.*}}, %[[S:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i128>{{.*}}
+subroutine dshiftr16_test(a, b, s, c)
+  integer(kind=16) :: a, b
+  integer :: s
+  integer(kind=16) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i128>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i128>
+  ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref<i32>
+  c = dshiftr(a, b, s)
+  ! CHECK: %[[S_CONV:.*]] = fir.convert %[[S_VAL]] : (i32) -> i128
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C_BITS]], %[[S_CONV]] : i128
+  ! CHECK: %[[C_BITS_L:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[C_0_L:.*]] = arith.constant 0 : i128
+  ! CHECK: %[[UNDER_L:.*]] = arith.cmpi slt, %[[DIFF]], %[[C_0_L]] : i128
+  ! CHECK: %[[OVER_L:.*]] = arith.cmpi sge, %[[DIFF]], %[[C_BITS_L]] : i128
+  ! CHECK: %[[INV_L:.*]] = arith.ori %[[UNDER_L]], %[[OVER_L]] : i1
+  ! CHECK: %[[SHL:.*]] = arith.shli %[[A_VAL]], %[[DIFF]] : i128
+  ! CHECK: %[[LFT:.*]] = arith.select %[[INV_L]], %[[C_0_L]], %[[SHL]] : i128
+  ! CHECK: %[[C_BITS_R:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[C_0_R:.*]] = arith.constant 0 : i128
+  ! CHECK: %[[UNDER_R:.*]] = arith.cmpi slt, %[[S_CONV]], %[[C_0_R]] : i128
+  ! CHECK: %[[OVER_R:.*]] = arith.cmpi sge, %[[S_CONV]], %[[C_BITS_R]] : i128
+  ! CHECK: %[[INV_R:.*]] = arith.ori %[[UNDER_R]], %[[OVER_R]] : i1
+  ! CHECK: %[[SHR:.*]] = arith.shrui %[[B_VAL]], %[[S_CONV]] : i128
+  ! CHECK: %[[RGT:.*]] = arith.select %[[INV_R]], %[[C_0_R]], %[[SHR]] : i128
+  ! CHECK: %[[SHIFT:.*]] = arith.ori %[[LFT]], %[[RGT]] : i128
+end subroutine dshiftr16_test

diff  --git a/flang/test/Lower/Intrinsics/shifta.f90 b/flang/test/Lower/Intrinsics/shifta.f90
new file mode 100644
index 000000000000..311206b213d2
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/shifta.f90
@@ -0,0 +1,101 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: shifta1_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i8>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i8>{{.*}}
+subroutine shifta1_test(a, b, c)
+  integer(kind=1) :: a
+  integer :: b
+  integer(kind=1) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i8>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shifta(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i8
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i8
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i8
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i8
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrsi %[[A_VAL]], %[[B_CONV]] : i8
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i8
+end subroutine shifta1_test
+
+! CHECK-LABEL: shifta2_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i16>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i16>{{.*}}
+subroutine shifta2_test(a, b, c)
+  integer(kind=2) :: a
+  integer :: b
+  integer(kind=2) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i16>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shifta(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i16
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i16
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i16
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i16
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrsi %[[A_VAL]], %[[B_CONV]] : i16
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i16
+end subroutine shifta2_test
+
+! CHECK-LABEL: shifta4_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i32>{{.*}}
+subroutine shifta4_test(a, b, c)
+  integer(kind=4) :: a
+  integer :: b
+  integer(kind=4) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shifta(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_VAL]], %[[C_0]] : i32
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_VAL]], %[[C_BITS]] : i32
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrsi %[[A_VAL]], %[[B_VAL]] : i32
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i32
+end subroutine shifta4_test
+
+! CHECK-LABEL: shifta8_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i64>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i64>{{.*}}
+subroutine shifta8_test(a, b, c)
+  integer(kind=8) :: a
+  integer :: b
+  integer(kind=8) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i64>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shifta(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i64
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i64
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i64
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrsi %[[A_VAL]], %[[B_CONV]] : i64
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i64
+end subroutine shifta8_test
+
+! CHECK-LABEL: shifta16_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i128>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i128>{{.*}}
+subroutine shifta16_test(a, b, c)
+  integer(kind=16) :: a
+  integer :: b
+  integer(kind=16) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i128>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shifta(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i128
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i128
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i128
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i128
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrsi %[[A_VAL]], %[[B_CONV]] : i128
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i128
+end subroutine shifta16_test

diff  --git a/flang/test/Lower/Intrinsics/shiftl.f90 b/flang/test/Lower/Intrinsics/shiftl.f90
new file mode 100644
index 000000000000..92414c2f7a92
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/shiftl.f90
@@ -0,0 +1,101 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: shiftl1_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i8>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i8>{{.*}}
+subroutine shiftl1_test(a, b, c)
+  integer(kind=1) :: a
+  integer :: b
+  integer(kind=1) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i8>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftl(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i8
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i8
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i8
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i8
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shli %[[A_VAL]], %[[B_CONV]] : i8
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i8
+end subroutine shiftl1_test
+
+! CHECK-LABEL: shiftl2_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i16>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i16>{{.*}}
+subroutine shiftl2_test(a, b, c)
+  integer(kind=2) :: a
+  integer :: b
+  integer(kind=2) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i16>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftl(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i16
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i16
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i16
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i16
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shli %[[A_VAL]], %[[B_CONV]] : i16
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i16
+end subroutine shiftl2_test
+
+! CHECK-LABEL: shiftl4_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i32>{{.*}}
+subroutine shiftl4_test(a, b, c)
+  integer(kind=4) :: a
+  integer :: b
+  integer(kind=4) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftl(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_VAL]], %[[C_0]] : i32
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_VAL]], %[[C_BITS]] : i32
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shli %[[A_VAL]], %[[B_VAL]] : i32
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i32
+end subroutine shiftl4_test
+
+! CHECK-LABEL: shiftl8_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i64>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i64>{{.*}}
+subroutine shiftl8_test(a, b, c)
+  integer(kind=8) :: a
+  integer :: b
+  integer(kind=8) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i64>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftl(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i64
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i64
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i64
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shli %[[A_VAL]], %[[B_CONV]] : i64
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i64
+end subroutine shiftl8_test
+
+! CHECK-LABEL: shiftl16_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i128>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i128>{{.*}}
+subroutine shiftl16_test(a, b, c)
+  integer(kind=16) :: a
+  integer :: b
+  integer(kind=16) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i128>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftl(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i128
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i128
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i128
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i128
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shli %[[A_VAL]], %[[B_CONV]] : i128
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i128
+end subroutine shiftl16_test

diff  --git a/flang/test/Lower/Intrinsics/shiftr.f90 b/flang/test/Lower/Intrinsics/shiftr.f90
new file mode 100644
index 000000000000..1015d1446195
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/shiftr.f90
@@ -0,0 +1,101 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: shiftr1_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i8>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i8>{{.*}}
+subroutine shiftr1_test(a, b, c)
+  integer(kind=1) :: a
+  integer :: b
+  integer(kind=1) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i8>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftr(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 8 : i8
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i8
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i8
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i8
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i8
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[A_VAL]], %[[B_CONV]] : i8
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i8
+end subroutine shiftr1_test
+
+! CHECK-LABEL: shiftr2_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i16>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i16>{{.*}}
+subroutine shiftr2_test(a, b, c)
+  integer(kind=2) :: a
+  integer :: b
+  integer(kind=2) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i16>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftr(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 16 : i16
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i16
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i16
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i16
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i16
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[A_VAL]], %[[B_CONV]] : i16
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i16
+end subroutine shiftr2_test
+
+! CHECK-LABEL: shiftr4_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i32>{{.*}}
+subroutine shiftr4_test(a, b, c)
+  integer(kind=4) :: a
+  integer :: b
+  integer(kind=4) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftr(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 32 : i32
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_VAL]], %[[C_0]] : i32
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_VAL]], %[[C_BITS]] : i32
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[A_VAL]], %[[B_VAL]] : i32
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i32
+end subroutine shiftr4_test
+
+! CHECK-LABEL: shiftr8_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i64>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i64>{{.*}}
+subroutine shiftr8_test(a, b, c)
+  integer(kind=8) :: a
+  integer :: b
+  integer(kind=8) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i64>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftr(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 64 : i64
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i64
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i64
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i64
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[A_VAL]], %[[B_CONV]] : i64
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i64
+end subroutine shiftr8_test
+
+! CHECK-LABEL: shiftr16_test
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i128>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<i128>{{.*}}
+subroutine shiftr16_test(a, b, c)
+  integer(kind=16) :: a
+  integer :: b
+  integer(kind=16) :: c
+
+  ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i128>
+  ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+  c = shiftr(a, b)
+  ! CHECK: %[[C_BITS:.*]] = arith.constant 128 : i128
+  ! CHECK: %[[C_0:.*]] = arith.constant 0 : i128
+  ! CHECK: %[[B_CONV:.*]] = fir.convert %[[B_VAL]] : (i32) -> i128
+  ! CHECK: %[[UNDER:.*]] = arith.cmpi slt, %[[B_CONV]], %[[C_0]] : i128
+  ! CHECK: %[[OVER:.*]] = arith.cmpi sge, %[[B_CONV]], %[[C_BITS]] : i128
+  ! CHECK: %[[INVALID:.*]] = arith.ori %[[UNDER]], %[[OVER]] : i1
+  ! CHECK: %[[SHIFT:.*]] = arith.shrui %[[A_VAL]], %[[B_CONV]] : i128
+  ! CHECK: %[[RES:.*]] = arith.select %[[INVALID]], %[[C_0]], %[[SHIFT]] : i128
+end subroutine shiftr16_test


        


More information about the flang-commits mailing list