This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-tirx.git


The following commit(s) were added to refs/heads/main by this push:
     new a51a6e758 [FIX] Parse device versions as integer components (#218)
a51a6e758 is described below

commit a51a6e758983cdb044b2387735c32d9700fb9504
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Nov 6 20:32:48 2026 -0500

    [FIX] Parse device versions as integer components (#218)
    
    Parse CUDA compute capabilities and OpenCL versions as integer
    major/minor components, and compare OpenCL versions lexicographically.
    This avoids interpreting version strings as locale-sensitive
    floating-point values.
    
    Remove the unused ARM architecture-version parsing helpers.
---
 src/backend/cuda/codegen/target_kind.cc         |  8 +++--
 src/backend/opencl/runtime/opencl_device_api.cc | 18 +++++-----
 src/codegen/llvm/canonicalizer/arm_aprofile.cc  | 19 ----------
 src/support/version.h                           | 47 +++++++++++++++++++++++++
 4 files changed, 62 insertions(+), 30 deletions(-)

diff --git a/src/backend/cuda/codegen/target_kind.cc 
b/src/backend/cuda/codegen/target_kind.cc
index d0d2d9938..ec750d687 100644
--- a/src/backend/cuda/codegen/target_kind.cc
+++ b/src/backend/cuda/codegen/target_kind.cc
@@ -35,6 +35,8 @@
 
 #include <string>
 
+#include "../../../support/version.h"
+
 namespace tvm {
 
 namespace backend {
@@ -83,7 +85,8 @@ ffi::Map<ffi::String, ffi::Any> 
UpdateCUDAAttrs(ffi::Map<ffi::String, ffi::Any>
       // Require an explicit architecture when resolving compilation, not here.
       return target;
     }
-    archInt = std::stod(version.cast<std::string>()) * 10 + 0.1;
+    auto [major, minor] = support::ParseVersion(version.cast<std::string>());
+    archInt = major * 10 + minor;
     if (archInt >= 90) {
       target.Set("arch", ffi::String("sm_") + std::to_string(archInt) + "a");
     } else {
@@ -106,7 +109,8 @@ ffi::Map<ffi::String, ffi::Any> 
UpdateNVPTXAttrs(ffi::Map<ffi::String, ffi::Any>
       LOG(WARNING) << "Unable to detect CUDA version, default to 
\"-mcpu=sm_50\" instead";
       arch = 50;
     } else {
-      arch = std::stod(version.cast<std::string>()) * 10 + 0.1;
+      auto [major, minor] = support::ParseVersion(version.cast<std::string>());
+      arch = major * 10 + minor;
     }
     target.Set("mcpu", ffi::String("sm_") + std::to_string(arch));
   }
diff --git a/src/backend/opencl/runtime/opencl_device_api.cc 
b/src/backend/opencl/runtime/opencl_device_api.cc
index 9d48a9bcd..864d7bc74 100644
--- a/src/backend/opencl/runtime/opencl_device_api.cc
+++ b/src/backend/opencl/runtime/opencl_device_api.cc
@@ -29,6 +29,7 @@
 
 #include <sstream>
 
+#include "../../../support/version.h"
 #include "../memory_scope.h"
 #include "opencl_common.h"
 
@@ -799,28 +800,27 @@ void OpenCLWorkspace::Init(const std::string& type_key, 
const std::string& devic
       }
       std::vector<cl_device_id> devices_matched = 
cl::GetDeviceIDs(platform_id, device_type);
       std::vector<cl_device_id> supported_devices = {};
-      auto get_version_str = [](int version) {
-        std::ostringstream out;
-        out.precision(1);
-        out << std::fixed << version / 100.f;
-        return out.str();
+      constexpr std::pair<int, int> target_version = {CL_TARGET_OPENCL_VERSION 
/ 100,
+                                                      CL_TARGET_OPENCL_VERSION 
% 100 / 10};
+      auto get_version_str = [](std::pair<int, int> version) {
+        return std::to_string(version.first) + "." + 
std::to_string(version.second);
       };
       for (auto& device : devices_matched) {
         std::string ver = GetOpenCLVersion(device);
-        int opencl_version = std::stod(ver) * 100;
-        if (opencl_version >= CL_TARGET_OPENCL_VERSION) {
+        auto opencl_version = support::ParseVersion(ver);
+        if (opencl_version >= target_version) {
           supported_devices.push_back(device);
         } else {
           std::string dev_msg = GetDeviceInfo(device, CL_DEVICE_NAME) +
                                 " has OpenCL version == " + 
get_version_str(opencl_version);
           LOG(WARNING) << "TVM supports devices with OpenCL version >= "
-                       << get_version_str(CL_TARGET_OPENCL_VERSION) << ", 
device " << dev_msg
+                       << get_version_str(target_version) << ", device " << 
dev_msg
                        << ". This device will be ignored.";
 
           if (noDevicesErrorMsg.empty()) {
             noDevicesErrorMsg =
                 "Probably this error happen because TVM supports devices with 
OpenCL version >= " +
-                get_version_str(CL_TARGET_OPENCL_VERSION) + ". We found the 
following devices:\n";
+                get_version_str(target_version) + ". We found the following 
devices:\n";
           }
           noDevicesErrorMsg += "\t" + dev_msg + "\n";
         }
diff --git a/src/codegen/llvm/canonicalizer/arm_aprofile.cc 
b/src/codegen/llvm/canonicalizer/arm_aprofile.cc
index cf1b3d78b..efaf89f1f 100644
--- a/src/codegen/llvm/canonicalizer/arm_aprofile.cc
+++ b/src/codegen/llvm/canonicalizer/arm_aprofile.cc
@@ -38,25 +38,6 @@ namespace canonicalizer {
 namespace llvm {
 namespace aprofile {
 
-double GetArchVersion(ffi::Array<ffi::String> mattr) {
-  for (const ffi::String& attr : mattr) {
-    std::string attr_string = attr;
-    size_t attr_len = attr_string.size();
-    if (attr_len >= 4 && attr_string.substr(0, 2) == "+v" && 
attr_string.back() == 'a') {
-      std::string version_string = attr_string.substr(2, attr_string.size() - 
2);
-      return atof(version_string.data());
-    }
-  }
-  return 0.0;
-}
-
-double GetArchVersion(ffi::Optional<ffi::Array<ffi::String>> attr) {
-  if (!attr) {
-    return false;
-  }
-  return GetArchVersion(attr.value());
-}
-
 bool IsAArch32(ffi::Optional<ffi::String> mtriple, ffi::Optional<ffi::String> 
mcpu) {
   if (mtriple) {
     bool is_mprofile = mcpu && mcpu.value().starts_with("cortex-m");
diff --git a/src/support/version.h b/src/support/version.h
new file mode 100644
index 000000000..ecc98eaac
--- /dev/null
+++ b/src/support/version.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*! \file version.h
+ * \brief Integer parsing for device version strings.
+ */
+#ifndef TVM_SUPPORT_VERSION_H_
+#define TVM_SUPPORT_VERSION_H_
+
+#include <string>
+#include <utility>
+
+namespace tvm {
+namespace support {
+
+inline std::pair<int, int> ParseVersion(const std::string& version) {
+  size_t end;
+  int major = std::stoi(version, &end);
+  int minor = 0;
+  // Like numeric prefix parsing, allow an absent minor or trailing vendor 
text.
+  if (end + 1 < version.size() && version[end] == '.' && version[end + 1] >= 
'0' &&
+      version[end + 1] <= '9') {
+    minor = std::stoi(version.substr(end + 1));
+  }
+  return {major, minor};
+}
+
+}  // namespace support
+}  // namespace tvm
+
+#endif  // TVM_SUPPORT_VERSION_H_

Reply via email to