[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