[flang] Removed dynamic loading feature for intrinsic folding
authorJean Perier <jperier@nvidia.com>
Thu, 21 Mar 2019 17:08:57 +0000 (10:08 -0700)
committerGitHub <noreply@github.com>
Wed, 27 Mar 2019 17:16:07 +0000 (10:16 -0700)
After more reflexion, dynamic loading brings to much uncertainty
regarding which library is actually being use for folding.
It is removed to avoid pushing people to use it.
A static linking to libpgmath will be provided in a later commit.

Original-commit: flang-compiler/f18@2161627d2896f06e763848443f61ae9624f03db1
Tree-same-pre-rewrite: false

flang/lib/evaluate/CMakeLists.txt
flang/lib/evaluate/intrinsics-library-templates.h
flang/lib/evaluate/intrinsics-library.cc
flang/lib/evaluate/intrinsics-library.h

index e06eb75..e4b66d2 100644 (file)
@@ -37,9 +37,3 @@ target_link_libraries(FortranEvaluate
   FortranParser
   m
 )
-
-IF(CMAKE_SYSTEM_NAME STREQUAL Linux)
-  target_link_libraries(FortranEvaluate
-    dl
-  )
-endif()
index 74d3a31..3a14ecf 100644 (file)
@@ -168,12 +168,5 @@ HostIntrinsicProceduresLibrary::GetHostProcedureWrapper(
   return std::nullopt;
 }
 
-template<typename TR, typename... ArgInfo>
-TargetRuntimeIntrinsicProcedure::TargetRuntimeIntrinsicProcedure(
-    const Signature<TR, ArgInfo...> &signature, const std::string &symbolName,
-    bool isElemental)
-  : IntrinsicProcedureRuntimeDescription{signature, isElemental},
-    symbol{symbolName} {}
-
 }
 #endif  // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_TEMPLATES_H_
index 261f1fa..c24ac56 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// This file defines the runtime libraries for the target as well as a default
-// set of host rte functions that can be used for folding.
+// This file defines host runtimes functions that can be used for folding
+// intrinsic functions.
 // The default HostIntrinsicProceduresLibrary is built with <cmath> and
 // <complex> functions that are guaranteed to exist from the C++ standard.
 
 #include <cerrno>
 #include <cfenv>
 #include <sstream>
-#if defined(__APPLE__) || defined(__unix__)
-#define IS_POSIX_COMPLIANT
-#include <dlfcn.h>
-#endif
 
 namespace Fortran::evaluate {
 
@@ -55,48 +51,7 @@ bool HostIntrinsicProceduresLibrary::HasEquivalentProcedure(
   return false;
 }
 
-void HostIntrinsicProceduresLibrary::LoadTargetIntrinsicProceduresLibrary(
-    const TargetIntrinsicProceduresLibrary &lib) {
-  if (dynamicallyLoadedLibraries.find(lib.name) !=
-      dynamicallyLoadedLibraries.end()) {
-    return;  // already loaded
-  }
-#ifdef IS_POSIX_COMPLIANT
-  void *handle = dlopen((lib.name + std::string{".so"}).c_str(), RTLD_LAZY);
-  if (!handle) {
-    return;
-  }
-  dynamicallyLoadedLibraries.insert(std::make_pair(lib.name, handle));
-  for (const auto &sym : lib.procedures) {
-    void *func{dlsym(handle, sym.second.symbol.c_str())};
-    auto error{dlerror()};
-    if (error) {
-    } else {
-      // Note: below is the only reinterpret_cast from an object pointer to
-      // function pointer As per C++11 and later rules on reinterpret_cast, it
-      // is implementation defined whether this is supported. POSIX mandates
-      // that such cast from function pointers to void* are defined. Hence this
-      // reinterpret_cast is and MUST REMAIN inside ifdef related to POSIX.
-      AddProcedure(HostRuntimeIntrinsicProcedure{
-          sym.second, reinterpret_cast<FuncPointer<void *>>(func)});
-    }
-  }
-#else
-  // TODO: systems that do not support dlopen (e.g windows)
-#endif
-}
-
-HostIntrinsicProceduresLibrary::~HostIntrinsicProceduresLibrary() {
-  for (auto iter{dynamicallyLoadedLibraries.begin()};
-       iter != dynamicallyLoadedLibraries.end(); ++iter) {
-#ifdef IS_POSIX_COMPLIANT
-    (void)dlclose(iter->second);
-#endif
-  }
-}
-
-// Map numerical intrinsic to  <cmath>/<complex> functions (for host folding
-// only)
+// Map numerical intrinsic to  <cmath>/<complex> functions
 
 // TODO mapping to <cmath> function to be tested.<cmath> func takes
 // real arg for n
@@ -148,92 +103,9 @@ void AddLibmComplexHostProcedure(
   }
 }
 
-// define mapping between numerical intrinsics and libpgmath symbols
-
-enum class MathOption { Fast, Precise, Relaxed };
-
-char constexpr inline EncodePgmMathOption(MathOption m) {
-  switch (m) {
-  case MathOption::Fast: return 'f';
-  case MathOption::Precise: return 'p';
-  case MathOption::Relaxed: return 'r';
-  }
-  return '\0';  // unreachable. Silencing bogus g++ warning
-}
-
-template<typename T> struct EncodePgmTypeHelper {};
-
-template<> struct EncodePgmTypeHelper<Type<TypeCategory::Real, 4>> {
-  static constexpr char value{'s'};
-};
-template<> struct EncodePgmTypeHelper<Type<TypeCategory::Real, 8>> {
-  static constexpr char value{'d'};
-};
-template<> struct EncodePgmTypeHelper<Type<TypeCategory::Complex, 4>> {
-  static constexpr char value{'c'};
-};
-template<> struct EncodePgmTypeHelper<Type<TypeCategory::Complex, 8>> {
-  static constexpr char value{'z'};
-};
-
-template<typename T>
-static constexpr char EncodePgmType{EncodePgmTypeHelper<T>::value};
-
-template<typename T>
-static std::string MakeLibpgmathName(const std::string &name, MathOption m) {
-  std::ostringstream stream;
-  stream << "__" << EncodePgmMathOption(m) << EncodePgmType<T> << "_" << name
-         << "_1";
-  // TODO Take mask and vector length into account
-  return stream.str();
-}
-
-template<typename T>
-static void AddLibpgmathTargetSymbols(
-    TargetIntrinsicProceduresLibrary &lib, MathOption opt) {
-  using F = Signature<T, ArgumentInfo<T, PassBy::Val>>;
-  const std::string oneArgFuncs[]{"acos", "asin", "atan", "cos", "cosh", "exp",
-      "log", "log10", "sin", "sinh", "tan", "tanh"};
-  for (const std::string &name : oneArgFuncs) {
-    lib.AddProcedure(TargetRuntimeIntrinsicProcedure{
-        F{name}, MakeLibpgmathName<T>(name, opt), true});
-  }
-
-  if constexpr (T::category == TypeCategory::Real) {
-    using F2 = Signature<T, ArgumentInfo<T, PassBy::Val>,
-        ArgumentInfo<T, PassBy::Val>>;
-    lib.AddProcedure(TargetRuntimeIntrinsicProcedure{
-        F2{"atan2"}, MakeLibpgmathName<T>("acos", opt), true});
-  } else {
-    const std::string oneArgCmplxFuncs[]{
-        "div", "sqrt"};  // for scalar, only complex available
-    for (const std::string &name : oneArgCmplxFuncs) {
-      lib.AddProcedure(TargetRuntimeIntrinsicProcedure{
-          F{name}, MakeLibpgmathName<T>(name, opt), true});
-    }
-  }
-}
-
-TargetIntrinsicProceduresLibrary BuildLibpgmTargetIntrinsicProceduresLibrary(
-    MathOption opt) {
-  TargetIntrinsicProceduresLibrary lib{"libpgmath"};
-  AddLibpgmathTargetSymbols<Type<TypeCategory::Real, 4>>(lib, opt);
-  AddLibpgmathTargetSymbols<Type<TypeCategory::Real, 8>>(lib, opt);
-  AddLibpgmathTargetSymbols<Type<TypeCategory::Complex, 4>>(lib, opt);
-  AddLibpgmathTargetSymbols<Type<TypeCategory::Complex, 8>>(lib, opt);
-  return lib;
-}
-
 // Defines which host runtime functions will be used for folding
 
 void HostIntrinsicProceduresLibrary::DefaultInit() {
-  // TODO: when linkage information is available, this needs to be modified to
-  // load runtime accordingly. For now, try loading libpgmath (libpgmath.so
-  // needs to be in a directory from LD_LIBRARY_PATH) and then add libm symbols
-  // when no equivalent symbols were already loaded
-  TargetIntrinsicProceduresLibrary libpgmath{
-      BuildLibpgmTargetIntrinsicProceduresLibrary(MathOption::Precise)};
-  LoadTargetIntrinsicProceduresLibrary(libpgmath);
 
   AddLibmRealHostProcedure<float>(*this);
   AddLibmRealHostProcedure<double>(*this);
index 36afb91..7575a0e 100644 (file)
 #ifndef FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_
 #define FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_
 
-// Defines structures to be used in F18 when dealing with the intrinsic
-// procedures runtime. It abstracts both:
-//  - the target intrinsic procedure runtime to be used for code generation
-//  - the host intrinsic runtime to be used for constant folding purposes.
-// To avoid unnecessary header circular dependencies, the actual implementation
-// of the templatized member function are defined in
+// Defines structures to be used in F18 for folding intrinsic function with host
+// runtime libraries. To avoid unnecessary header circular dependencies, the
+// actual implementation of the templatized member function are defined in
 // intrinsics-library-templates.h The header at hand is meant to be included by
 // files that need to define intrinsic runtime data structure but that do not
 // use them directly. To actually use the runtime data structures,
-// intrinsics-library-templates.h must be included Note that
-// intrinsics-library-templates.h includes the header at hand.
+// intrinsics-library-templates.h must be included.
 
 #include <functional>
 #include <map>
@@ -62,38 +58,12 @@ struct IntrinsicProcedureRuntimeDescription {
   const std::vector<PassBy> argumentsPassedBy;
   const bool isElemental;
   const FuncPointer<void *> callable;
-  // callable only usable by HostRuntimeIntrinsicProcedure but need to be
-  // created in case TargetRuntimeIntrinsicProcedure is dynamically loaded
-  // because creating it dynamically would be too complex
-
   // Construct from description using host independent types (RuntimeTypes)
   template<typename TR, typename... ArgInfo>
   IntrinsicProcedureRuntimeDescription(
       const Signature<TR, ArgInfo...> &signature, bool isElemental = false);
 };
 
-// TargetRuntimeIntrinsicProcedure holds target runtime information
-// for an intrinsics procedure.
-struct TargetRuntimeIntrinsicProcedure : IntrinsicProcedureRuntimeDescription {
-  // Construct from description using host independent types (RuntimeTypes)
-  // Note: passing ref/val also needs to be passed by template to build
-  // the callable
-  template<typename TR, typename... ArgInfo>
-  TargetRuntimeIntrinsicProcedure(const Signature<TR, ArgInfo...> &signature,
-      const std::string &symbolName, bool isElemental = false);
-  const std::string symbol;
-};
-
-struct TargetIntrinsicProceduresLibrary {
-  TargetIntrinsicProceduresLibrary(const std::string &name) : name{name} {}
-  void AddProcedure(TargetRuntimeIntrinsicProcedure &&sym) {
-    const std::string name{sym.name};
-    procedures.insert(std::make_pair(name, std::move(sym)));
-  }
-  const std::string name;
-  std::multimap<std::string, const TargetRuntimeIntrinsicProcedure> procedures;
-};
-
 // HostRuntimeIntrinsicProcedure allows host runtime function to be called for
 // constant folding.
 struct HostRuntimeIntrinsicProcedure : IntrinsicProcedureRuntimeDescription {
@@ -119,9 +89,7 @@ using HostProcedureWrapper = std::function<ConstantContainer<TR>(
 // HostRuntimeIntrinsicProcedure elements. It is meant for constant folding.
 // When queried for an intrinsic procedure, it can return a callable object that
 // implements this intrinsic if a host runtime function pointer for this
-// intrinsic was added to its data structure. It can also dynamically load
-// function pointer from a TargetIntrinsicProceduresLibrary if the related
-// library is available on the host.
+// intrinsic was added to its data structure.
 struct HostIntrinsicProceduresLibrary {
   void AddProcedure(HostRuntimeIntrinsicProcedure &&sym) {
     const std::string name{sym.name};
@@ -130,18 +98,12 @@ struct HostIntrinsicProceduresLibrary {
   bool HasEquivalentProcedure(
       const IntrinsicProcedureRuntimeDescription &sym) const;
   HostIntrinsicProceduresLibrary() { DefaultInit(); }
-  ~HostIntrinsicProceduresLibrary();
-  void DefaultInit();  // Try loading libpgmath functions and then load
-                       // functions from <cmath> and <complex>
-  void LoadTargetIntrinsicProceduresLibrary(
-      const TargetIntrinsicProceduresLibrary &lib);
+  void DefaultInit();
   template<template<typename> typename ConstantContainer, typename TR,
       typename... TA>
   std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>>
   GetHostProcedureWrapper(const std::string &name);
   std::multimap<std::string, const HostRuntimeIntrinsicProcedure> procedures;
-  std::map<std::string, void *>
-      dynamicallyLoadedLibraries;  // keep the handles for dlclose
 };
 
 }