diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp index 7bdfe508511f3..e5036a3daaa42 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); mlir::Value genDprod(mlir::Type, llvm::ArrayRef); + mlir::Value genDshiftl(mlir::Type, llvm::ArrayRef); + mlir::Value genDshiftr(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genEoshift(mlir::Type, llvm::ArrayRef); void genExit(llvm::ArrayRef); mlir::Value genExponent(mlir::Type, llvm::ArrayRef); @@ -543,6 +545,8 @@ struct IntrinsicLibrary { fir::ExtendedValue genScan(mlir::Type, llvm::ArrayRef); mlir::Value genSetExponent(mlir::Type resultType, llvm::ArrayRef args); + template + mlir::Value genShift(mlir::Type resultType, llvm::ArrayRef); mlir::Value genSign(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef); 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}, + {"shiftl", &I::genShift}, + {"shiftr", &I::genShift}, {"sign", &I::genSign}, {"size", &I::genSize, @@ -2664,6 +2673,54 @@ mlir::Value IntrinsicLibrary::genDprod(mlir::Type resultType, return builder.create(loc, a, b); } +// DSHIFTL +mlir::Value IntrinsicLibrary::genDshiftl(mlir::Type resultType, + llvm::ArrayRef 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(loc, bitSize, shift); + + mlir::Value lArgs[2]{i, shift}; + mlir::Value lft = genShift(resultType, lArgs); + + mlir::Value rArgs[2]{j, diff}; + mlir::Value rgt = genShift(resultType, rArgs); + + return builder.create(loc, lft, rgt); +} + +// DSHIFTR +mlir::Value IntrinsicLibrary::genDshiftr(mlir::Type resultType, + llvm::ArrayRef 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(loc, bitSize, shift); + + mlir::Value lArgs[2]{i, diff}; + mlir::Value lft = genShift(resultType, lArgs); + + mlir::Value rArgs[2]{j, shift}; + mlir::Value rgt = genShift(resultType, rArgs); + + return builder.create(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 +mlir::Value IntrinsicLibrary::genShift(mlir::Type resultType, + llvm::ArrayRef 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( + loc, mlir::arith::CmpIPredicate::slt, shift, zero); + mlir::Value tooLarge = builder.create( + loc, mlir::arith::CmpIPredicate::sge, shift, bitSize); + mlir::Value outOfBounds = + builder.create(loc, tooSmall, tooLarge); + + mlir::Value shifted = builder.create(loc, args[0], shift); + return builder.create(loc, outOfBounds, zero, shifted); +} + // SIGN mlir::Value IntrinsicLibrary::genSign(mlir::Type resultType, llvm::ArrayRef args) { diff --git a/flang/test/Lower/Intrinsics/dshiftl.f90 b/flang/test/Lower/Intrinsics/dshiftl.f90 new file mode 100644 index 0000000000000..809bd83d03f82 --- /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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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 0000000000000..565e142a4a066 --- /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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[S:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +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 + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + ! CHECK: %[[S_VAL:.*]] = fir.load %[[S]] : !fir.ref + 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 0000000000000..311206b213d22 --- /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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shifta1_test(a, b, c) + integer(kind=1) :: a + integer :: b + integer(kind=1) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shifta2_test(a, b, c) + integer(kind=2) :: a + integer :: b + integer(kind=2) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shifta4_test(a, b, c) + integer(kind=4) :: a + integer :: b + integer(kind=4) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shifta8_test(a, b, c) + integer(kind=8) :: a + integer :: b + integer(kind=8) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shifta16_test(a, b, c) + integer(kind=16) :: a + integer :: b + integer(kind=16) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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 0000000000000..92414c2f7a92e --- /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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftl1_test(a, b, c) + integer(kind=1) :: a + integer :: b + integer(kind=1) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftl2_test(a, b, c) + integer(kind=2) :: a + integer :: b + integer(kind=2) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftl4_test(a, b, c) + integer(kind=4) :: a + integer :: b + integer(kind=4) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftl8_test(a, b, c) + integer(kind=8) :: a + integer :: b + integer(kind=8) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftl16_test(a, b, c) + integer(kind=16) :: a + integer :: b + integer(kind=16) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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 0000000000000..1015d1446195e --- /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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftr1_test(a, b, c) + integer(kind=1) :: a + integer :: b + integer(kind=1) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftr2_test(a, b, c) + integer(kind=2) :: a + integer :: b + integer(kind=2) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftr4_test(a, b, c) + integer(kind=4) :: a + integer :: b + integer(kind=4) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftr8_test(a, b, c) + integer(kind=8) :: a + integer :: b + integer(kind=8) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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{{.*}}, %[[B:.*]]: !fir.ref{{.*}}, %[[C:.*]]: !fir.ref{{.*}} +subroutine shiftr16_test(a, b, c) + integer(kind=16) :: a + integer :: b + integer(kind=16) :: c + + ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref + ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref + 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