[flang-commits] [flang] 2f80b73 - [flang] Fold BTEST

peter klausler via flang-commits flang-commits at lists.llvm.org
Mon Oct 18 13:46:56 PDT 2021


Author: peter klausler
Date: 2021-10-18T13:46:46-07:00
New Revision: 2f80b73e0cf03ddfebc5d0851d5fae29fe1de5d0

URL: https://github.com/llvm/llvm-project/commit/2f80b73e0cf03ddfebc5d0851d5fae29fe1de5d0
DIFF: https://github.com/llvm/llvm-project/commit/2f80b73e0cf03ddfebc5d0851d5fae29fe1de5d0.diff

LOG: [flang] Fold BTEST

Implements constant folding for BTEST intrinsic function.

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

Added: 
    flang/test/Evaluate/fold-btest.f90

Modified: 
    flang/include/flang/Evaluate/type.h
    flang/lib/Evaluate/fold-logical.cpp
    flang/test/Evaluate/folding19.f90

Removed: 
    


################################################################################
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 <TypeCategory CATEGORY, int KIND = 0> class Type;
 
 using SubscriptInteger = Type<TypeCategory::Integer, 8>;
 using CInteger = Type<TypeCategory::Integer, 4>;
+using LargestInt = Type<TypeCategory::Integer, 16>;
 using LogicalResult = Type<TypeCategory::Logical, 4>;
 using LargestReal = Type<TypeCategory::Real, 16>;
 using Ascii = Type<TypeCategory::Character, 1>;

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<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
   auto *intrinsic{std::get_if<SpecificIntrinsic>(&funcRef.proc().u)};
   CHECK(intrinsic);
   std::string name{intrinsic->name};
+  using SameInt = Type<TypeCategory::Integer, KIND>;
   if (name == "all") {
     return FoldAllAny(
         context, std::move(funcRef), &Scalar<T>::AND, Scalar<T>{true});
@@ -59,7 +60,6 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
     }
     return gotConstant ? Expr<T>{false} : Expr<T>{std::move(funcRef)};
   } else if (name == "bge" || name == "bgt" || name == "ble" || name == "blt") {
-    using LargestInt = Type<TypeCategory::Integer, 16>;
     static_assert(std::is_same_v<Scalar<LargestInt>, 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<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
             [&fptr](const Scalar<LargestInt> &i, const Scalar<LargestInt> &j) {
               return Scalar<T>{std::invoke(fptr, i, j)};
             }));
+  } else if (name == "btest") {
+    if (const auto *ix{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
+      return std::visit(
+          [&](const auto &x) {
+            using IT = ResultType<decltype(x)>;
+            return FoldElementalIntrinsic<T, IT, SameInt>(context,
+                std::move(funcRef),
+                ScalarFunc<T, IT, SameInt>(
+                    [&](const Scalar<IT> &x, const Scalar<SameInt> &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<std::intmax_t>(posVal));
+                      }
+                      return Scalar<T>{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<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
       name == "__builtin_ieee_support_underflow_control") {
     return Expr<T>{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<T>{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


        


More information about the flang-commits mailing list