[Openmp-commits] [openmp] 411a8ee - [libomp] Parse OMP_DEFAULT_DEVICE with new device trait parser (#176166)
via Openmp-commits
openmp-commits at lists.llvm.org
Wed Sep 9 02:15:05 PDT 2026
Author: Robert Imschweiler
Date: 2026-09-09T11:15:00+02:00
New Revision: 411a8eea0c269fff79700da1b3a9e71914718d4b
URL: https://github.com/llvm/llvm-project/commit/411a8eea0c269fff79700da1b3a9e71914718d4b
DIFF: https://github.com/llvm/llvm-project/commit/411a8eea0c269fff79700da1b3a9e71914718d4b.diff
LOG: [libomp] Parse OMP_DEFAULT_DEVICE with new device trait parser (#176166)
... but do not yet expose the new functionalities to the user. This is a
backward compatible update that is going to be followed by the step to
the OpenMP 6.0 semantics as defined in 4.3.8.
Added:
Modified:
openmp/runtime/src/i18n/en_US.txt
openmp/runtime/src/kmp_settings.cpp
openmp/runtime/src/kmp_traits.cpp
openmp/runtime/src/kmp_traits.h
openmp/runtime/unittests/Traits/TestOMPTraitParser.cpp
Removed:
################################################################################
diff --git a/openmp/runtime/src/i18n/en_US.txt b/openmp/runtime/src/i18n/en_US.txt
index 3b7187edaeb13..84a515383a805 100644
--- a/openmp/runtime/src/i18n/en_US.txt
+++ b/openmp/runtime/src/i18n/en_US.txt
@@ -366,6 +366,9 @@ TraitParserError "trait parser while parsing %1$s: error: %2$s"
TraitParserInvalidTraitValue "trait parser while parsing %1$s: invalid value for trait '%2$s' (%3$s)"
TraitParserMaxRecursion "trait parser while parsing %1$s: max recursion depth (%2$d) exceeded"
TraitParserFailed "trait parser while parsing %1$s: failed to parse trait specification (%2$s)"
+TraitParserValueTooSmall "trait parser while parsing %1$s: value %2$d below limit (%3$d)"
+TraitParserValueTooLarge "trait parser while parsing %1$s: value %2$d above limit (%3$d)"
+TraitParserLegacyFailed "legacy device number parser while parsing %1$s: failed to parse device number (%2$s)"
# --- OpenMP errors detected at runtime ---
#
diff --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp
index 8cd69099c9ca4..3ab604e15c017 100644
--- a/openmp/runtime/src/kmp_settings.cpp
+++ b/openmp/runtime/src/kmp_settings.cpp
@@ -23,6 +23,7 @@
#include "kmp_lock.h"
#include "kmp_settings.h"
#include "kmp_str.h"
+#include "kmp_traits.h"
#include "kmp_wrapper_getpid.h"
#include <ctype.h> // toupper()
#if OMPD_SUPPORT
@@ -1420,8 +1421,8 @@ static void __kmp_stg_print_max_active_levels(kmp_str_buf_t *buffer,
// OpenMP 4.0: OMP_DEFAULT_DEVICE
static void __kmp_stg_parse_default_device(char const *name, char const *value,
void *data) {
- __kmp_stg_parse_int(name, value, 0, KMP_MAX_DEFAULT_DEVICE_LIMIT,
- &__kmp_default_device);
+ __kmp_default_device = kmp_trait_context::parse_single_device(
+ value, /*device_num_min=*/0, KMP_MAX_DEFAULT_DEVICE_LIMIT, name);
} // __kmp_stg_parse_default_device
static void __kmp_stg_print_default_device(kmp_str_buf_t *buffer,
diff --git a/openmp/runtime/src/kmp_traits.cpp b/openmp/runtime/src/kmp_traits.cpp
index 6070f388ec1d2..021dbbc90e3ad 100644
--- a/openmp/runtime/src/kmp_traits.cpp
+++ b/openmp/runtime/src/kmp_traits.cpp
@@ -421,3 +421,27 @@ kmp_trait_context *kmp_trait_context::parse_from_spec(kmp_str_ref spec,
parser::consume_list(*context, lex, dbg_name);
return context;
}
+
+int kmp_trait_context::parse_single_device(kmp_str_ref spec, int device_num_min,
+ int device_num_max,
+ const char *dbg_name) {
+ int device_num;
+ kmp_str_ref orig_spec = spec;
+
+ spec.skip_space();
+ if (!spec.consume_integer(device_num, /*allow_zero=*/true,
+ /*allow_negative=*/true))
+ KMP_FATAL(TraitParserLegacyFailed, dbg_name, orig_spec.copy());
+ spec.skip_space();
+ if (!spec.empty())
+ KMP_FATAL(TraitParserLegacyFailed, dbg_name, orig_spec.copy());
+
+ if (device_num < device_num_min) {
+ KMP_WARNING(TraitParserValueTooSmall, dbg_name, device_num, device_num_min);
+ device_num = device_num_min;
+ } else if (device_num > device_num_max) {
+ KMP_WARNING(TraitParserValueTooLarge, dbg_name, device_num, device_num_max);
+ device_num = device_num_max;
+ }
+ return device_num;
+}
diff --git a/openmp/runtime/src/kmp_traits.h b/openmp/runtime/src/kmp_traits.h
index 66913bd9db22c..796e9fc771938 100644
--- a/openmp/runtime/src/kmp_traits.h
+++ b/openmp/runtime/src/kmp_traits.h
@@ -438,6 +438,14 @@ class kmp_trait_context final {
static kmp_trait_context *parse_from_spec(kmp_str_ref spec,
const char *dbg_name = nullptr);
+ // Parse only a single device number from the spec.
+ // This is useful for backward compatibility with legacy code.
+ // If dbg_name is provided, it will be used in error messages to identify the
+ // source of the device number.
+ static int parse_single_device(kmp_str_ref spec, int device_num_min,
+ int device_num_max,
+ const char *dbg_name = nullptr);
+
void add_clause(kmp_trait_clause *clause) {
assert(clause);
clauses.push_back(clause);
diff --git a/openmp/runtime/unittests/Traits/TestOMPTraitParser.cpp b/openmp/runtime/unittests/Traits/TestOMPTraitParser.cpp
index 59e2c4b07318a..633468bf28f37 100644
--- a/openmp/runtime/unittests/Traits/TestOMPTraitParser.cpp
+++ b/openmp/runtime/unittests/Traits/TestOMPTraitParser.cpp
@@ -1069,4 +1069,109 @@ TEST_F(ParserTest, MaxRecursionExceeded) {
"max recursion depth \\(64\\) exceeded");
}
+//===----------------------------------------------------------------------===//
+// parse_single_device Tests
+//===----------------------------------------------------------------------===//
+
+TEST(ParseSingleDeviceTest, ValidSingleDigit) {
+ int result = kmp_trait_context::parse_single_device(kmp_str_ref("5"), 0, 10);
+ EXPECT_EQ(result, 5);
+}
+
+TEST(ParseSingleDeviceTest, ValidMultiDigit) {
+ int result =
+ kmp_trait_context::parse_single_device(kmp_str_ref("123"), 0, 200);
+ EXPECT_EQ(result, 123);
+}
+
+TEST(ParseSingleDeviceTest, Zero) {
+ int result = kmp_trait_context::parse_single_device(kmp_str_ref("0"), 0, 10);
+ EXPECT_EQ(result, 0);
+}
+
+TEST(ParseSingleDeviceTest, AtMax) {
+ int result = kmp_trait_context::parse_single_device(kmp_str_ref("10"), 0, 10);
+ EXPECT_EQ(result, 10);
+}
+
+TEST(ParseSingleDeviceTest, AtMin) {
+ int result = kmp_trait_context::parse_single_device(kmp_str_ref("2"), 2, 10);
+ EXPECT_EQ(result, 2);
+}
+
+TEST(ParseSingleDeviceTest, AboveMaxClampsToMax) {
+ // Values above the maximum are warned about and clamped to the maximum.
+ int result = kmp_trait_context::parse_single_device(kmp_str_ref("11"), 0, 10);
+ EXPECT_EQ(result, 10);
+}
+
+TEST(ParseSingleDeviceTest, BelowMinClampsToMin) {
+ // Values below the minimum are warned about and clamped to the minimum.
+ int result = kmp_trait_context::parse_single_device(kmp_str_ref("2"), 5, 10);
+ EXPECT_EQ(result, 5);
+}
+
+TEST(ParseSingleDeviceTest, NegativeValue) {
+ // Negative device numbers are allowed within range.
+ int result =
+ kmp_trait_context::parse_single_device(kmp_str_ref("-1"), -5, 10);
+ EXPECT_EQ(result, -1);
+}
+
+TEST(ParseSingleDeviceTest, NegativeBelowMinClampsToMin) {
+ // Negative values below the minimum are clamped to the minimum.
+ int result = kmp_trait_context::parse_single_device(kmp_str_ref("-7"), 0, 10);
+ EXPECT_EQ(result, 0);
+}
+
+TEST(ParseSingleDeviceTest, NonInteger) {
+ ASSERT_DEATH(kmp_trait_context::parse_single_device(kmp_str_ref("abc"), 0, 10,
+ "non_integer"),
+ "OMP: Error #[0-9]+: legacy device number parser while parsing "
+ "non_integer: failed to parse device number \\(abc\\)");
+}
+
+TEST(ParseSingleDeviceTest, EmptyString) {
+ ASSERT_DEATH(
+ kmp_trait_context::parse_single_device(kmp_str_ref(""), 0, 10, "empty"),
+ "OMP: Error #[0-9]+: legacy device number parser while parsing empty: "
+ "failed to parse device number \\(\\)");
+}
+
+TEST(ParseSingleDeviceTest, LeadingSpaces) {
+ // consume_integer skips leading spaces
+ int result =
+ kmp_trait_context::parse_single_device(kmp_str_ref(" 7"), 0, 10);
+ EXPECT_EQ(result, 7);
+}
+
+TEST(ParseSingleDeviceTest, LargeNumber) {
+ int result =
+ kmp_trait_context::parse_single_device(kmp_str_ref("999999"), 0, 1000000);
+ EXPECT_EQ(result, 999999);
+}
+
+TEST(ParseSingleDeviceTest, TrailingGarbage) {
+ // Trailing non-integer characters must not be silently ignored.
+ ASSERT_DEATH(kmp_trait_context::parse_single_device(kmp_str_ref("10abc"), 0,
+ 100, "trailing_garbage"),
+ "OMP: Error #[0-9]+: legacy device number parser while parsing "
+ "trailing_garbage: failed to parse device number \\(10abc\\)");
+}
+
+TEST(ParseSingleDeviceTest, TrailingList) {
+ // Only a single device is accepted; a comma-separated list must fail.
+ ASSERT_DEATH(kmp_trait_context::parse_single_device(kmp_str_ref("10,11"), 0,
+ 100, "trailing_list"),
+ "OMP: Error #[0-9]+: legacy device number parser while parsing "
+ "trailing_list: failed to parse device number \\(10,11\\)");
+}
+
+TEST(ParseSingleDeviceTest, TrailingSpaces) {
+ // Trailing whitespace is allowed.
+ int result =
+ kmp_trait_context::parse_single_device(kmp_str_ref("7 "), 0, 10);
+ EXPECT_EQ(result, 7);
+}
+
} // namespace
More information about the Openmp-commits
mailing list