diff --git a/flang/include/flang/Evaluate/type.h b/flang/include/flang/Evaluate/type.h index dcc052769b786..c413e24cf3190 100644 --- a/flang/include/flang/Evaluate/type.h +++ b/flang/include/flang/Evaluate/type.h @@ -50,6 +50,7 @@ template class Type; using SubscriptInteger = Type; using CInteger = Type; +using LargestInt = Type; using LogicalResult = Type; using LargestReal = Type; using Ascii = Type; diff --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp index 586909d3ecf83..62bc37282fe78 100644 --- a/flang/lib/Evaluate/fold-logical.cpp +++ b/flang/lib/Evaluate/fold-logical.cpp @@ -40,6 +40,7 @@ Expr> FoldIntrinsicFunction( auto *intrinsic{std::get_if(&funcRef.proc().u)}; CHECK(intrinsic); std::string name{intrinsic->name}; + using SameInt = Type; if (name == "all") { return FoldAllAny( context, std::move(funcRef), &Scalar::AND, Scalar{true}); @@ -59,7 +60,6 @@ Expr> FoldIntrinsicFunction( } return gotConstant ? Expr{false} : Expr{std::move(funcRef)}; } else if (name == "bge" || name == "bgt" || name == "ble" || name == "blt") { - using LargestInt = Type; static_assert(std::is_same_v, BOZLiteralConstant>); // Arguments do not have to be of the same integer type. Convert all // arguments to the biggest integer type before comparing them to @@ -89,6 +89,26 @@ Expr> FoldIntrinsicFunction( [&fptr](const Scalar &i, const Scalar &j) { return Scalar{std::invoke(fptr, i, j)}; })); + } else if (name == "btest") { + if (const auto *ix{UnwrapExpr>(args[0])}) { + return std::visit( + [&](const auto &x) { + using IT = ResultType; + return FoldElementalIntrinsic(context, + std::move(funcRef), + ScalarFunc( + [&](const Scalar &x, const Scalar &pos) { + auto posVal{pos.ToInt64()}; + if (posVal < 0 || posVal >= x.bits) { + context.messages().Say( + "POS=%jd out of range for BTEST"_err_en_US, + static_cast(posVal)); + } + return Scalar{x.BTEST(posVal)}; + })); + }, + ix->u); + } } else if (name == "isnan" || name == "__builtin_ieee_is_nan") { // A warning about an invalid argument is discarded from converting // the argument of isnan() / IEEE_IS_NAN(). @@ -139,7 +159,7 @@ Expr> FoldIntrinsicFunction( name == "__builtin_ieee_support_underflow_control") { return Expr{true}; } - // TODO: btest, dot_product, is_iostat_end, + // TODO: dot_product, is_iostat_end, // is_iostat_eor, logical, matmul, out_of_range, // parity, transfer return Expr{std::move(funcRef)}; diff --git a/flang/test/Evaluate/fold-btest.f90 b/flang/test/Evaluate/fold-btest.f90 new file mode 100644 index 0000000000000..e346dd0c65fac --- /dev/null +++ b/flang/test/Evaluate/fold-btest.f90 @@ -0,0 +1,21 @@ +! RUN: %python %S/test_folding.py %s %flang_fc1 +! Tests folding of BTEST +module m1 + integer, parameter :: ia1(*) = [(j, j=0, 15)] + logical, parameter :: test_ia1a = all(btest(ia1, 0) .eqv. [(.false., .true., j=1, 8)]) + logical, parameter :: test_ia1b = all(btest(ia1, 1) .eqv. [(.false., .false., .true., .true., j=1, 4)]) + logical, parameter :: test_ia1c = all(btest(ia1, 2) .eqv. [(modulo(j/4, 2) == 1, j=0, 15)]) + logical, parameter :: test_ia1d = all(btest(ia1, 3) .eqv. [(j > 8, j=1, 16)]) + logical, parameter :: test_shft1 = all([(btest(ishft(1_1, j), j), j=0, 7)]) + logical, parameter :: test_shft2 = all([(btest(ishft(1_2, j), j), j=0, 15)]) + logical, parameter :: test_shft4 = all([(btest(ishft(1_4, j), j), j=0, 31)]) + logical, parameter :: test_shft8 = all([(btest(ishft(1_8, j), j), j=0, 63)]) + logical, parameter :: test_shft16 = all([(btest(ishft(1_16, j), j), j=0, 127)]) + logical, parameter :: test_set1 = all([(btest(ibset(0_1, j), j), j=0, 7)]) + logical, parameter :: test_set2 = all([(btest(ibset(0_2, j), j), j=0, 15)]) + logical, parameter :: test_set4 = all([(btest(ibset(0_4, j), j), j=0, 31)]) + logical, parameter :: test_set8 = all([(btest(ibset(0_8, j), j), j=0, 63)]) + logical, parameter :: test_set16 = all([(btest(ibset(0_16, j), j), j=0, 127)]) + logical, parameter :: test_z = .not. any([(btest(0_4, j), j=0, 31)]) + logical, parameter :: test_shft1e = all(btest([(ishft(1_1, j), j=0, 7)], [(j, j=0, 7)])) +end module diff --git a/flang/test/Evaluate/folding19.f90 b/flang/test/Evaluate/folding19.f90 index 8cfaeb155a150..cbd6d2082b52a 100644 --- a/flang/test/Evaluate/folding19.f90 +++ b/flang/test/Evaluate/folding19.f90 @@ -50,4 +50,14 @@ subroutine s5 !CHECK: error: Invalid 'vector=' argument in UNPACK: the 'mask=' argument has 3 true elements, but the vector has only 2 elements x = unpack([1,2], mask, 0) end subroutine + subroutine s6 + !CHECK: error: POS=-1 out of range for BTEST + logical, parameter :: bad1 = btest(0, -1) + !CHECK: error: POS=32 out of range for BTEST + logical, parameter :: bad2 = btest(0, 32) + !CHECK-NOT: error: POS=33 out of range for BTEST + logical, parameter :: bad3 = btest(0_8, 33) + !CHECK: error: POS=64 out of range for BTEST + logical, parameter :: bad4 = btest(0_8, 64) + end subroutine end module