[flang] Lower F08 shift intrinsics
authorTarun Prabhu <tarun.prabhu@gmail.com>
Fri, 22 Jul 2022 05:36:08 +0000 (23:36 -0600)
committerTarun Prabhu <tarun.prabhu@gmail.com>
Fri, 22 Jul 2022 05:36:08 +0000 (23:36 -0600)
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

flang/lib/Lower/IntrinsicCall.cpp
flang/test/Lower/Intrinsics/dshiftl.f90 [new file with mode: 0644]
flang/test/Lower/Intrinsics/dshiftr.f90 [new file with mode: 0644]
flang/test/Lower/Intrinsics/shifta.f90 [new file with mode: 0644]
flang/test/Lower/Intrinsics/shiftl.f90 [new file with mode: 0644]
flang/test/Lower/Intrinsics/shiftr.f90 [new file with mode: 0644]

index 7bdfe50..e5036a3 100644 (file)
@@ -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 (file)
index 0000000..809bd83
--- /dev/null
@@ -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 (file)
index 0000000..565e142
--- /dev/null
@@ -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 (file)
index 0000000..311206b
--- /dev/null
@@ -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 (file)
index 0000000..92414c2
--- /dev/null
@@ -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 (file)
index 0000000..1015d14
--- /dev/null
@@ -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