[Openmp-commits] [openmp] [OpenMP][NFC] Separate Envar (environment variable) handling (PR #73994)
Johannes Doerfert via Openmp-commits
openmp-commits at lists.llvm.org
Thu Nov 30 14:18:47 PST 2023
https://github.com/jdoerfert created https://github.com/llvm/llvm-project/pull/73994
None
>From d358c108f6b0f36a09a83c49e2de7d8551cdd53b Mon Sep 17 00:00:00 2001
From: Johannes Doerfert <johannes at jdoerfert.de>
Date: Thu, 30 Nov 2023 13:11:27 -0800
Subject: [PATCH] [OpenMP][NFC] Separate Envar (environment variable) handling
---
.../include/Shared/EnvironmentVar.h | 194 ++++++++++++++++++
openmp/libomptarget/include/Shared/Utils.h | 177 ----------------
.../plugins-nextgen/common/include/JIT.h | 23 +--
.../common/include/MemoryManager.h | 2 +-
.../common/include/PluginInterface.h | 1 +
openmp/libomptarget/src/device.cpp | 7 +-
openmp/libomptarget/src/interface.cpp | 2 +-
openmp/libomptarget/src/rtl.cpp | 2 +-
8 files changed, 212 insertions(+), 196 deletions(-)
create mode 100644 openmp/libomptarget/include/Shared/EnvironmentVar.h
diff --git a/openmp/libomptarget/include/Shared/EnvironmentVar.h b/openmp/libomptarget/include/Shared/EnvironmentVar.h
new file mode 100644
index 000000000000000..4cbdad695a0ee14
--- /dev/null
+++ b/openmp/libomptarget/include/Shared/EnvironmentVar.h
@@ -0,0 +1,194 @@
+//===-- Shared/EnvironmentVar.h - Environment variable handling -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OMPTARGET_SHARED_ENVIRONMENT_VAR_H
+#define OMPTARGET_SHARED_ENVIRONMENT_VAR_H
+
+#include "Debug.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+#include <sstream>
+#include <string>
+
+/// Utility class for parsing strings to other types.
+struct StringParser {
+ /// Parse a string to another type.
+ template <typename Ty> static bool parse(const char *Value, Ty &Result);
+};
+
+/// Class for reading and checking environment variables. Currently working with
+/// integer, floats, std::string and bool types.
+template <typename Ty> class Envar {
+ Ty Data;
+ bool IsPresent;
+ bool Initialized;
+
+public:
+ /// Auxiliary function to safely create envars. This static function safely
+ /// creates envars using fallible constructors. See the constructors to know
+ /// more details about the creation parameters.
+ template <typename... ArgsTy>
+ static llvm::Expected<Envar> create(ArgsTy &&...Args) {
+ llvm::Error Err = llvm::Error::success();
+ Envar Envar(std::forward<ArgsTy>(Args)..., Err);
+ if (Err)
+ return std::move(Err);
+ return std::move(Envar);
+ }
+
+ /// Create an empty envar. Cannot be consulted. This constructor is merely
+ /// for convenience. This constructor is not fallible.
+ Envar() : Data(Ty()), IsPresent(false), Initialized(false) {}
+
+ /// Create an envar with a name and an optional default. The Envar object will
+ /// take the value read from the environment variable, or the default if it
+ /// was not set or not correct. This constructor is not fallible.
+ Envar(llvm::StringRef Name, Ty Default = Ty())
+ : Data(Default), IsPresent(false), Initialized(true) {
+
+ if (const char *EnvStr = getenv(Name.data())) {
+ // Check whether the envar is defined and valid.
+ IsPresent = StringParser::parse<Ty>(EnvStr, Data);
+
+ if (!IsPresent) {
+ DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
+ Data = Default;
+ }
+ }
+ }
+
+ Envar<Ty> &operator=(const Ty &V) {
+ Data = V;
+ Initialized = true;
+ return *this;
+ }
+
+ /// Get the definitive value.
+ const Ty &get() const {
+ // Throw a runtime error in case this envar is not initialized.
+ if (!Initialized)
+ FATAL_MESSAGE0(1, "Consulting envar before initialization");
+
+ return Data;
+ }
+
+ /// Get the definitive value.
+ operator Ty() const { return get(); }
+
+ /// Indicate whether the environment variable was defined and valid.
+ bool isPresent() const { return IsPresent; }
+
+private:
+ /// This constructor should never fail but we provide it for convenience. This
+ /// way, the constructor can be used by the Envar::create() static function
+ /// to safely create this kind of envars.
+ Envar(llvm::StringRef Name, Ty Default, llvm::Error &Err)
+ : Envar(Name, Default) {
+ llvm::ErrorAsOutParameter EAO(&Err);
+ Err = llvm::Error::success();
+ }
+
+ /// Create an envar with a name, getter function and a setter function. The
+ /// Envar object will take the value read from the environment variable if
+ /// this value is accepted by the setter function. Otherwise, the getter
+ /// function will be executed to get the default value. The getter should be
+ /// of the form Error GetterFunctionTy(Ty &Value) and the setter should
+ /// be of the form Error SetterFunctionTy(Ty Value). This constructor has a
+ /// private visibility because is a fallible constructor. Please use the
+ /// Envar::create() static function to safely create this object instead.
+ template <typename GetterFunctor, typename SetterFunctor>
+ Envar(llvm::StringRef Name, GetterFunctor Getter, SetterFunctor Setter,
+ llvm::Error &Err)
+ : Data(Ty()), IsPresent(false), Initialized(true) {
+ llvm::ErrorAsOutParameter EAO(&Err);
+ Err = init(Name, Getter, Setter);
+ }
+
+ template <typename GetterFunctor, typename SetterFunctor>
+ llvm::Error init(llvm::StringRef Name, GetterFunctor Getter,
+ SetterFunctor Setter);
+};
+
+/// Define some common envar types.
+using IntEnvar = Envar<int>;
+using Int32Envar = Envar<int32_t>;
+using Int64Envar = Envar<int64_t>;
+using UInt32Envar = Envar<uint32_t>;
+using UInt64Envar = Envar<uint64_t>;
+using StringEnvar = Envar<std::string>;
+using BoolEnvar = Envar<bool>;
+
+template <>
+inline bool StringParser::parse(const char *ValueStr, bool &Result) {
+ std::string Value(ValueStr);
+
+ // Convert the string to lowercase.
+ std::transform(Value.begin(), Value.end(), Value.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+
+ // May be implemented with fancier C++ features, but let's keep it simple.
+ if (Value == "true" || Value == "yes" || Value == "on" || Value == "1")
+ Result = true;
+ else if (Value == "false" || Value == "no" || Value == "off" || Value == "0")
+ Result = false;
+ else
+ return false;
+
+ // Parsed correctly.
+ return true;
+}
+
+template <typename Ty>
+inline bool StringParser::parse(const char *Value, Ty &Result) {
+ assert(Value && "Parsed value cannot be null");
+
+ std::istringstream Stream(Value);
+ Stream >> Result;
+
+ return !Stream.fail();
+}
+
+template <typename Ty>
+template <typename GetterFunctor, typename SetterFunctor>
+inline llvm::Error Envar<Ty>::init(llvm::StringRef Name, GetterFunctor Getter,
+ SetterFunctor Setter) {
+ // Get the default value.
+ Ty Default;
+ if (llvm::Error Err = Getter(Default))
+ return Err;
+
+ if (const char *EnvStr = getenv(Name.data())) {
+ IsPresent = StringParser::parse<Ty>(EnvStr, Data);
+ if (IsPresent) {
+ // Check whether the envar value is actually valid.
+ llvm::Error Err = Setter(Data);
+ if (Err) {
+ // The setter reported an invalid value. Mark the user-defined value as
+ // not present and reset to the getter value (default).
+ IsPresent = false;
+ Data = Default;
+ DP("Setter of envar %s failed, resetting to %s\n", Name.data(),
+ std::to_string(Data).data());
+ consumeError(std::move(Err));
+ }
+ } else {
+ DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
+ Data = Default;
+ }
+ } else {
+ Data = Default;
+ }
+
+ return llvm::Error::success();
+}
+
+#endif // OMPTARGET_SHARED_ENVIRONMENT_VAR_H
diff --git a/openmp/libomptarget/include/Shared/Utils.h b/openmp/libomptarget/include/Shared/Utils.h
index b6bb97ce59496cc..fce14b54edb9892 100644
--- a/openmp/libomptarget/include/Shared/Utils.h
+++ b/openmp/libomptarget/include/Shared/Utils.h
@@ -15,131 +15,18 @@
#define OMPTARGET_SHARED_UTILS_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
#include "Debug.h"
-#include <algorithm>
#include <atomic>
#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-#include <functional>
#include <limits>
#include <memory>
-#include <sstream>
-#include <string>
namespace llvm {
namespace omp {
namespace target {
-/// Utility class for parsing strings to other types.
-struct StringParser {
- /// Parse a string to another type.
- template <typename Ty> static bool parse(const char *Value, Ty &Result);
-};
-
-/// Class for reading and checking environment variables. Currently working with
-/// integer, floats, std::string and bool types.
-template <typename Ty> class Envar {
- Ty Data;
- bool IsPresent;
- bool Initialized;
-
-public:
- /// Auxiliary function to safely create envars. This static function safely
- /// creates envars using fallible constructors. See the constructors to know
- /// more details about the creation parameters.
- template <typename... ArgsTy>
- static Expected<Envar> create(ArgsTy &&...Args) {
- Error Err = Error::success();
- Envar Envar(std::forward<ArgsTy>(Args)..., Err);
- if (Err)
- return std::move(Err);
- return std::move(Envar);
- }
-
- /// Create an empty envar. Cannot be consulted. This constructor is merely
- /// for convenience. This constructor is not fallible.
- Envar() : Data(Ty()), IsPresent(false), Initialized(false) {}
-
- /// Create an envar with a name and an optional default. The Envar object will
- /// take the value read from the environment variable, or the default if it
- /// was not set or not correct. This constructor is not fallible.
- Envar(StringRef Name, Ty Default = Ty())
- : Data(Default), IsPresent(false), Initialized(true) {
-
- if (const char *EnvStr = getenv(Name.data())) {
- // Check whether the envar is defined and valid.
- IsPresent = StringParser::parse<Ty>(EnvStr, Data);
-
- if (!IsPresent) {
- DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
- Data = Default;
- }
- }
- }
-
- Envar<Ty> &operator=(const Ty &V) {
- Data = V;
- Initialized = true;
- return *this;
- }
-
- /// Get the definitive value.
- const Ty &get() const {
- // Throw a runtime error in case this envar is not initialized.
- if (!Initialized)
- FATAL_MESSAGE0(1, "Consulting envar before initialization");
-
- return Data;
- }
-
- /// Get the definitive value.
- operator Ty() const { return get(); }
-
- /// Indicate whether the environment variable was defined and valid.
- bool isPresent() const { return IsPresent; }
-
-private:
- /// This constructor should never fail but we provide it for convenience. This
- /// way, the constructor can be used by the Envar::create() static function
- /// to safely create this kind of envars.
- Envar(StringRef Name, Ty Default, Error &Err) : Envar(Name, Default) {
- ErrorAsOutParameter EAO(&Err);
- Err = Error::success();
- }
-
- /// Create an envar with a name, getter function and a setter function. The
- /// Envar object will take the value read from the environment variable if
- /// this value is accepted by the setter function. Otherwise, the getter
- /// function will be executed to get the default value. The getter should be
- /// of the form Error GetterFunctionTy(Ty &Value) and the setter should
- /// be of the form Error SetterFunctionTy(Ty Value). This constructor has a
- /// private visibility because is a fallible constructor. Please use the
- /// Envar::create() static function to safely create this object instead.
- template <typename GetterFunctor, typename SetterFunctor>
- Envar(StringRef Name, GetterFunctor Getter, SetterFunctor Setter, Error &Err)
- : Data(Ty()), IsPresent(false), Initialized(true) {
- ErrorAsOutParameter EAO(&Err);
- Err = init(Name, Getter, Setter);
- }
-
- template <typename GetterFunctor, typename SetterFunctor>
- Error init(StringRef Name, GetterFunctor Getter, SetterFunctor Setter);
-};
-
-/// Define some common envar types.
-using IntEnvar = Envar<int>;
-using Int32Envar = Envar<int32_t>;
-using Int64Envar = Envar<int64_t>;
-using UInt32Envar = Envar<uint32_t>;
-using UInt64Envar = Envar<uint64_t>;
-using StringEnvar = Envar<std::string>;
-using BoolEnvar = Envar<bool>;
-
/// Utility class for thread-safe reference counting. Any class that needs
/// objects' reference counting can inherit from this entity or have it as a
/// class data member.
@@ -170,70 +57,6 @@ struct RefCountTy {
std::atomic<Ty> Refs;
};
-template <>
-inline bool StringParser::parse(const char *ValueStr, bool &Result) {
- std::string Value(ValueStr);
-
- // Convert the string to lowercase.
- std::transform(Value.begin(), Value.end(), Value.begin(),
- [](unsigned char c) { return std::tolower(c); });
-
- // May be implemented with fancier C++ features, but let's keep it simple.
- if (Value == "true" || Value == "yes" || Value == "on" || Value == "1")
- Result = true;
- else if (Value == "false" || Value == "no" || Value == "off" || Value == "0")
- Result = false;
- else
- return false;
-
- // Parsed correctly.
- return true;
-}
-
-template <typename Ty>
-inline bool StringParser::parse(const char *Value, Ty &Result) {
- assert(Value && "Parsed value cannot be null");
-
- std::istringstream Stream(Value);
- Stream >> Result;
-
- return !Stream.fail();
-}
-
-template <typename Ty>
-template <typename GetterFunctor, typename SetterFunctor>
-inline Error Envar<Ty>::init(StringRef Name, GetterFunctor Getter,
- SetterFunctor Setter) {
- // Get the default value.
- Ty Default;
- if (Error Err = Getter(Default))
- return Err;
-
- if (const char *EnvStr = getenv(Name.data())) {
- IsPresent = StringParser::parse<Ty>(EnvStr, Data);
- if (IsPresent) {
- // Check whether the envar value is actually valid.
- Error Err = Setter(Data);
- if (Err) {
- // The setter reported an invalid value. Mark the user-defined value as
- // not present and reset to the getter value (default).
- IsPresent = false;
- Data = Default;
- DP("Setter of envar %s failed, resetting to %s\n", Name.data(),
- std::to_string(Data).data());
- consumeError(std::move(Err));
- }
- } else {
- DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
- Data = Default;
- }
- } else {
- Data = Default;
- }
-
- return Error::success();
-}
-
/// Return the difference (in bytes) between \p Begin and \p End.
template <typename Ty = char>
ptrdiff_t getPtrDiff(const void *End, const void *Begin) {
diff --git a/openmp/libomptarget/plugins-nextgen/common/include/JIT.h b/openmp/libomptarget/plugins-nextgen/common/include/JIT.h
index 1a5e56b2ea732a6..7252519a8c2eb3a 100644
--- a/openmp/libomptarget/plugins-nextgen/common/include/JIT.h
+++ b/openmp/libomptarget/plugins-nextgen/common/include/JIT.h
@@ -11,6 +11,7 @@
#ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_JIT_H
#define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_JIT_H
+#include "Shared/EnvironmentVar.h"
#include "Shared/Utils.h"
#include "llvm/ADT/StringMap.h"
@@ -106,18 +107,16 @@ struct JITEngine {
std::mutex ComputeUnitMapMutex;
/// Control environment variables.
- target::StringEnvar ReplacementObjectFileName =
- target::StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_OBJECT");
- target::StringEnvar ReplacementModuleFileName =
- target::StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_MODULE");
- target::StringEnvar PreOptIRModuleFileName =
- target::StringEnvar("LIBOMPTARGET_JIT_PRE_OPT_IR_MODULE");
- target::StringEnvar PostOptIRModuleFileName =
- target::StringEnvar("LIBOMPTARGET_JIT_POST_OPT_IR_MODULE");
- target::UInt32Envar JITOptLevel =
- target::UInt32Envar("LIBOMPTARGET_JIT_OPT_LEVEL", 3);
- target::BoolEnvar JITSkipOpt =
- target::BoolEnvar("LIBOMPTARGET_JIT_SKIP_OPT", false);
+ StringEnvar ReplacementObjectFileName =
+ StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_OBJECT");
+ StringEnvar ReplacementModuleFileName =
+ StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_MODULE");
+ StringEnvar PreOptIRModuleFileName =
+ StringEnvar("LIBOMPTARGET_JIT_PRE_OPT_IR_MODULE");
+ StringEnvar PostOptIRModuleFileName =
+ StringEnvar("LIBOMPTARGET_JIT_POST_OPT_IR_MODULE");
+ UInt32Envar JITOptLevel = UInt32Envar("LIBOMPTARGET_JIT_OPT_LEVEL", 3);
+ BoolEnvar JITSkipOpt = BoolEnvar("LIBOMPTARGET_JIT_SKIP_OPT", false);
};
} // namespace target
diff --git a/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h b/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h
index 95491b4be6fa6f0..fe1989930b76ef7 100644
--- a/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h
+++ b/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h
@@ -324,7 +324,7 @@ class MemoryManagerTy {
/// manager explicitly by setting the var to 0. If user doesn't specify
/// anything, returns <0, true>.
static std::pair<size_t, bool> getSizeThresholdFromEnv() {
- static llvm::omp::target::UInt32Envar MemoryManagerThreshold(
+ static UInt32Envar MemoryManagerThreshold(
"LIBOMPTARGET_MEMORY_MANAGER_THRESHOLD", 0);
size_t Threshold = MemoryManagerThreshold.get();
diff --git a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h
index 6abd1b6829ab554..dd601e6b4231aae 100644
--- a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h
+++ b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h
@@ -21,6 +21,7 @@
#include "Shared/Debug.h"
#include "Shared/Environment.h"
+#include "Shared/EnvironmentVar.h"
#include "Shared/Utils.h"
#include "GlobalHandler.h"
diff --git a/openmp/libomptarget/src/device.cpp b/openmp/libomptarget/src/device.cpp
index 2431d7c073352ab..da7d33b3f40c629 100644
--- a/openmp/libomptarget/src/device.cpp
+++ b/openmp/libomptarget/src/device.cpp
@@ -18,7 +18,7 @@
#include "private.h"
#include "rtl.h"
-#include "Shared/Utils.h"
+#include "Shared/EnvironmentVar.h"
#include <cassert>
#include <climits>
@@ -535,11 +535,10 @@ void DeviceTy::init() {
return;
// Enables recording kernels if set.
- llvm::omp::target::BoolEnvar OMPX_RecordKernel("LIBOMPTARGET_RECORD", false);
+ BoolEnvar OMPX_RecordKernel("LIBOMPTARGET_RECORD", false);
if (OMPX_RecordKernel) {
// Enables saving the device memory kernel output post execution if set.
- llvm::omp::target::BoolEnvar OMPX_ReplaySaveOutput(
- "LIBOMPTARGET_RR_SAVE_OUTPUT", false);
+ BoolEnvar OMPX_ReplaySaveOutput("LIBOMPTARGET_RR_SAVE_OUTPUT", false);
uint64_t ReqPtrArgOffset;
RTL->initialize_record_replay(RTLDeviceID, 0, nullptr, true,
diff --git a/openmp/libomptarget/src/interface.cpp b/openmp/libomptarget/src/interface.cpp
index 97cada94527f0ff..a2f713459e1d0c9 100644
--- a/openmp/libomptarget/src/interface.cpp
+++ b/openmp/libomptarget/src/interface.cpp
@@ -19,8 +19,8 @@
#include "private.h"
#include "rtl.h"
+#include "Shared/EnvironmentVar.h"
#include "Shared/Profile.h"
-#include "Shared/Utils.h"
#include "Utils/ExponentialBackoff.h"
diff --git a/openmp/libomptarget/src/rtl.cpp b/openmp/libomptarget/src/rtl.cpp
index e80d6e09c4840bc..09084be12a76e2a 100644
--- a/openmp/libomptarget/src/rtl.cpp
+++ b/openmp/libomptarget/src/rtl.cpp
@@ -14,11 +14,11 @@
#include "OpenMP/OMPT/Callback.h"
#include "PluginManager.h"
-#include "Shared/Debug.h"
#include "device.h"
#include "private.h"
#include "rtl.h"
+#include "Shared/Debug.h"
#include "Shared/Profile.h"
#include "Shared/Utils.h"
More information about the Openmp-commits
mailing list