[flang-commits] [flang] 5c5bde1 - [flang] Fold SCALE()

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Sat Jan 15 09:31:07 PST 2022


Author: Peter Klausler
Date: 2022-01-15T09:31:00-08:00
New Revision: 5c5bde1bb6e451e0014067802bc6a9d7b1314636

URL: https://github.com/llvm/llvm-project/commit/5c5bde1bb6e451e0014067802bc6a9d7b1314636
DIFF: https://github.com/llvm/llvm-project/commit/5c5bde1bb6e451e0014067802bc6a9d7b1314636.diff

LOG: [flang] Fold SCALE()

Fold references to the intrinsic function SCALE().

(Also work around some MSVC headaches somehow exposed by
this patch: disable a bogus MSVC warning that began to appear
in unrelated source files, and avoid the otherwise-necessary
use of the "template" keyword in a call to a template member
function of a class template.)

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

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

Modified: 
    flang/include/flang/Evaluate/real.h
    flang/lib/Evaluate/constant.cpp
    flang/lib/Evaluate/expression.cpp
    flang/lib/Evaluate/fold-character.cpp
    flang/lib/Evaluate/fold-complex.cpp
    flang/lib/Evaluate/fold-integer.cpp
    flang/lib/Evaluate/fold-logical.cpp
    flang/lib/Evaluate/fold-real.cpp
    flang/lib/Evaluate/formatting.cpp
    flang/lib/Evaluate/variable.cpp
    flang/test/Evaluate/errors01.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h
index 8f497401b46e5..77c25c4feae17 100644
--- a/flang/include/flang/Evaluate/real.h
+++ b/flang/include/flang/Evaluate/real.h
@@ -155,6 +155,26 @@ class Real : public common::RealDetails<PREC> {
   static constexpr int MAXEXPONENT{maxExponent - exponentBias};
   static constexpr int MINEXPONENT{2 - exponentBias};
 
+  // SCALE(); also known as IEEE_SCALB and (in IEEE-754 '08) ScaleB.
+  template <typename INT>
+  ValueWithRealFlags<Real> SCALE(
+      const INT &by, Rounding rounding = defaultRounding) const {
+    auto expo{exponentBias + by.ToInt64()};
+    if (IsZero()) {
+      expo = exponentBias; // ignore by, don't overflow
+    } else if (by > INT{maxExponent}) {
+      expo = maxExponent;
+    } else if (by < INT{-exponentBias}) {
+      expo = -1;
+    }
+    Real twoPow;
+    RealFlags flags{
+        twoPow.Normalize(false, static_cast<int>(expo), Fraction::MASKL(1))};
+    ValueWithRealFlags<Real> result{Multiply(twoPow, rounding)};
+    result.flags |= flags;
+    return result;
+  }
+
   constexpr Real FlushSubnormalToZero() const {
     if (IsSubnormal()) {
       return Real{};

diff  --git a/flang/lib/Evaluate/constant.cpp b/flang/lib/Evaluate/constant.cpp
index 199b19003cf7f..a4f5f72a35c7b 100644
--- a/flang/lib/Evaluate/constant.cpp
+++ b/flang/lib/Evaluate/constant.cpp
@@ -342,5 +342,8 @@ bool ComponentCompare::operator()(SymbolRef x, SymbolRef y) const {
   return semantics::SymbolSourcePositionCompare{}(x, y);
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 INSTANTIATE_CONSTANT_TEMPLATES
 } // namespace Fortran::evaluate

diff  --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp
index 576e3309d536e..1f255e61f37a9 100644
--- a/flang/lib/Evaluate/expression.cpp
+++ b/flang/lib/Evaluate/expression.cpp
@@ -324,5 +324,8 @@ std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
   return std::visit([](const auto &kx) { return kx.LEN(); }, u);
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 INSTANTIATE_EXPRESSION_TEMPLATES
 } // namespace Fortran::evaluate

diff  --git a/flang/lib/Evaluate/fold-character.cpp b/flang/lib/Evaluate/fold-character.cpp
index 72e124a6a84b2..ed07b7ab62531 100644
--- a/flang/lib/Evaluate/fold-character.cpp
+++ b/flang/lib/Evaluate/fold-character.cpp
@@ -140,6 +140,9 @@ Expr<Type<TypeCategory::Character, KIND>> FoldOperation(
   return Expr<Result>{std::move(x)};
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 FOR_EACH_CHARACTER_KIND(template class ExpressionBase, )
 template class ExpressionBase<SomeCharacter>;
 } // namespace Fortran::evaluate

diff  --git a/flang/lib/Evaluate/fold-complex.cpp b/flang/lib/Evaluate/fold-complex.cpp
index d259561739db2..7458aa9ca9596 100644
--- a/flang/lib/Evaluate/fold-complex.cpp
+++ b/flang/lib/Evaluate/fold-complex.cpp
@@ -78,6 +78,9 @@ Expr<Type<TypeCategory::Complex, KIND>> FoldOperation(
   return Expr<Result>{std::move(x)};
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 FOR_EACH_COMPLEX_KIND(template class ExpressionBase, )
 template class ExpressionBase<SomeComplex>;
 } // namespace Fortran::evaluate

diff  --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp
index f7a661da2f800..2618949b29d84 100644
--- a/flang/lib/Evaluate/fold-integer.cpp
+++ b/flang/lib/Evaluate/fold-integer.cpp
@@ -1020,6 +1020,9 @@ std::optional<std::int64_t> ToInt64(const Expr<SomeType> &expr) {
   }
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 FOR_EACH_INTEGER_KIND(template class ExpressionBase, )
 template class ExpressionBase<SomeInteger>;
 } // namespace Fortran::evaluate

diff  --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp
index 62bc37282fe78..4ba4ce8387609 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -254,6 +254,9 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldOperation(
   return Expr<LOGICAL>{std::move(operation)};
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 FOR_EACH_LOGICAL_KIND(template class ExpressionBase, )
 template class ExpressionBase<SomeLogical>;
 } // namespace Fortran::evaluate

diff  --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp
index f7c7f5713fd8d..0a7e16161cf5a 100644
--- a/flang/lib/Evaluate/fold-real.cpp
+++ b/flang/lib/Evaluate/fold-real.cpp
@@ -130,6 +130,31 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
     if (auto *expr{args[0].value().UnwrapExpr()}) {
       return ToReal<KIND>(context, std::move(*expr));
     }
+  } else if (name == "scale") {
+    if (const auto *byExpr{UnwrapExpr<Expr<SomeInteger>>(args[1])}) {
+      return std::visit(
+          [&](const auto &byVal) {
+            using TBY = ResultType<decltype(byVal)>;
+            return FoldElementalIntrinsic<T, T, TBY>(context,
+                std::move(funcRef),
+                ScalarFunc<T, T, TBY>(
+                    [&](const Scalar<T> &x, const Scalar<TBY> &y) -> Scalar<T> {
+                      ValueWithRealFlags<Scalar<T>> result{x.
+// MSVC chokes on the keyword "template" here in a call to a
+// member function template.
+#ifndef _MSC_VER
+                                                           template
+#endif
+                                                           SCALE(y)};
+                      if (result.flags.test(RealFlag::Overflow)) {
+                        context.messages().Say(
+                            "SCALE intrinsic folding overflow"_en_US);
+                      }
+                      return result.value;
+                    }));
+          },
+          byExpr->u);
+    }
   } else if (name == "sign") {
     return FoldElementalIntrinsic<T, T, T>(
         context, std::move(funcRef), &Scalar<T>::SIGN);
@@ -143,7 +168,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
     return Expr<T>{Scalar<T>::TINY()};
   }
   // TODO: dim, dot_product, fraction, matmul,
-  // modulo, nearest, norm2, rrspacing, scale,
+  // modulo, nearest, norm2, rrspacing,
   // __builtin_next_after/down/up,
   // set_exponent, spacing, transfer,
   // bessel_jn (transformational) and bessel_yn (transformational)
@@ -175,6 +200,9 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(
   return Expr<Part>{std::move(x)};
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 FOR_EACH_REAL_KIND(template class ExpressionBase, )
 template class ExpressionBase<SomeReal>;
 } // namespace Fortran::evaluate

diff  --git a/flang/lib/Evaluate/formatting.cpp b/flang/lib/Evaluate/formatting.cpp
index 674c55504f32a..062fec42d7fbe 100644
--- a/flang/lib/Evaluate/formatting.cpp
+++ b/flang/lib/Evaluate/formatting.cpp
@@ -785,6 +785,9 @@ llvm::raw_ostream &Assignment::AsFortran(llvm::raw_ostream &o) const {
   return o;
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 INSTANTIATE_CONSTANT_TEMPLATES
 INSTANTIATE_EXPRESSION_TEMPLATES
 INSTANTIATE_VARIABLE_TEMPLATES

diff  --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp
index b33a77f351319..21a0e6b439f44 100644
--- a/flang/lib/Evaluate/variable.cpp
+++ b/flang/lib/Evaluate/variable.cpp
@@ -685,6 +685,9 @@ bool DescriptorInquiry::operator==(const DescriptorInquiry &that) const {
       dimension_ == that.dimension_;
 }
 
+#ifdef _MSC_VER // disable bogus warning about missing definitions
+#pragma warning(disable : 4661)
+#endif
 INSTANTIATE_VARIABLE_TEMPLATES
 } // namespace Fortran::evaluate
 

diff  --git a/flang/test/Evaluate/errors01.f90 b/flang/test/Evaluate/errors01.f90
index 2ba5444da9315..50705be17a390 100644
--- a/flang/test/Evaluate/errors01.f90
+++ b/flang/test/Evaluate/errors01.f90
@@ -100,4 +100,10 @@ subroutine s9
     !CHECK: error: DIM=4 argument to SPREAD must be between 1 and 3
     integer, parameter :: bad3 = spread(matrix, 4, 1)
   end subroutine
+  subroutine warnings
+    real, parameter :: ok1 = scale(0.0, 99999) ! 0.0
+    real, parameter :: ok2 = scale(1.0, -99999) ! 0.0
+    !CHECK: SCALE intrinsic folding overflow
+    real, parameter :: bad1 = scale(1.0, 99999)
+  end subroutine
 end module

diff  --git a/flang/test/Evaluate/fold-scale.f90 b/flang/test/Evaluate/fold-scale.f90
new file mode 100644
index 0000000000000..a5c5f081668b1
--- /dev/null
+++ b/flang/test/Evaluate/fold-scale.f90
@@ -0,0 +1,11 @@
+! RUN: %python %S/test_folding.py %s %flang_fc1
+! Tests folding of SCALE()
+module m
+  logical, parameter :: test_1 = scale(1.0, 1) == 2.0
+  logical, parameter :: test_2 = scale(0.0, 1) == 0.0
+  logical, parameter :: test_3 = sign(1.0, scale(-0.0, 1)) == -1.0
+  logical, parameter :: test_4 = sign(1.0, scale(0.0, 0)) == 1.0
+  logical, parameter :: test_5 = scale(1.0, -1) == 0.5
+  logical, parameter :: test_6 = scale(2.0, -1) == 1.0
+end module
+


        


More information about the flang-commits mailing list