File: folding.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (84 lines) | stat: -rw-r--r-- 3,399 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "testing.h"
#include "../../lib/Evaluate/host.h"
#include "flang/Evaluate/call.h"
#include "flang/Evaluate/expression.h"
#include "flang/Evaluate/fold.h"
#include "flang/Evaluate/intrinsics-library.h"
#include "flang/Evaluate/intrinsics.h"
#include "flang/Evaluate/target.h"
#include "flang/Evaluate/tools.h"
#include <tuple>

using namespace Fortran::evaluate;

// helper to call functions on all types from tuple
template <typename... T> struct RunOnTypes {};
template <typename Test, typename... T>
struct RunOnTypes<Test, std::tuple<T...>> {
  static void Run() { (..., Test::template Run<T>()); }
};

// test for fold.h GetScalarConstantValue function
struct TestGetScalarConstantValue {
  template <typename T> static void Run() {
    Expr<T> exprFullyTyped{Constant<T>{Scalar<T>{}}};
    Expr<SomeKind<T::category>> exprSomeKind{exprFullyTyped};
    Expr<SomeType> exprSomeType{exprSomeKind};
    TEST(GetScalarConstantValue<T>(exprFullyTyped).has_value());
    TEST(GetScalarConstantValue<T>(exprSomeKind).has_value());
    TEST(GetScalarConstantValue<T>(exprSomeType).has_value());
  }
};

template <typename T>
Scalar<T> CallHostRt(
    HostRuntimeWrapper func, FoldingContext &context, Scalar<T> x) {
  return GetScalarConstantValue<T>(
      func(context, {AsGenericExpr(Constant<T>{x})}))
      .value();
}

void TestHostRuntimeSubnormalFlushing() {
  using R4 = Type<TypeCategory::Real, 4>;
  if constexpr (std::is_same_v<host::HostType<R4>, float>) {
    Fortran::parser::CharBlock src;
    Fortran::parser::ContextualMessages messages{src, nullptr};
    Fortran::common::IntrinsicTypeDefaultKinds defaults;
    auto intrinsics{Fortran::evaluate::IntrinsicProcTable::Configure(defaults)};
    TargetCharacteristics flushingTargetCharacteristics;
    flushingTargetCharacteristics.set_areSubnormalsFlushedToZero(true);
    TargetCharacteristics noFlushingTargetCharacteristics;
    noFlushingTargetCharacteristics.set_areSubnormalsFlushedToZero(false);
    FoldingContext flushingContext{
        messages, defaults, intrinsics, flushingTargetCharacteristics};
    FoldingContext noFlushingContext{
        messages, defaults, intrinsics, noFlushingTargetCharacteristics};

    DynamicType r4{R4{}.GetType()};
    // Test subnormal argument flushing
    if (auto callable{GetHostRuntimeWrapper("log", r4, {r4})}) {
      // Biggest IEEE 32bits subnormal power of two
      const Scalar<R4> x1{Scalar<R4>::Word{0x00400000}};
      Scalar<R4> y1Flushing{CallHostRt<R4>(*callable, flushingContext, x1)};
      Scalar<R4> y1NoFlushing{CallHostRt<R4>(*callable, noFlushingContext, x1)};
      // We would expect y1Flushing to be NaN, but some libc logf implementation
      // "workaround" subnormal flushing by returning a constant negative
      // results for all subnormal values (-1.03972076416015625e2_4). In case of
      // flushing, the result should still be different than -88 +/- 2%.
      TEST(y1Flushing.IsInfinite() ||
          std::abs(host::CastFortranToHost<R4>(y1Flushing) + 88.) > 2);
      TEST(!y1NoFlushing.IsInfinite() &&
          std::abs(host::CastFortranToHost<R4>(y1NoFlushing) + 88.) < 2);
    } else {
      TEST(false);
    }
  } else {
    TEST(false); // Cannot run this test on the host
  }
}

int main() {
  RunOnTypes<TestGetScalarConstantValue, AllIntrinsicTypes>::Run();
  TestHostRuntimeSubnormalFlushing();
  return testing::Complete();
}