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

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


The following commit(s) were added to refs/heads/main by this push:
     new f0ac8d62ef [REFACTOR][RUNTIME] Phase out tvm::runtime::regex_match 
(#19620)
f0ac8d62ef is described below

commit f0ac8d62efed35793010bff59ce67a22e0344d5d
Author: Tianqi Chen <[email protected]>
AuthorDate: Wed May 27 15:30:27 2026 -0400

    [REFACTOR][RUNTIME] Phase out tvm::runtime::regex_match (#19620)
    
    ## Summary
    
    `tvm::runtime::regex_match` was a thin C++ wrapper that bounced through
    a
    global `ffi::Function` back into Python's `re.match`. It was introduced
    solely to avoid pulling `<regex>` into TVM (libstdc++ dual-ABI conflict
    with
    pre-cxx11 pytorch wheels). The only C++ caller is the DNNL JSON runtime,
    where
    every pattern reduces to substring containment — `re.match` anchors at
    the
    start only, so `.*X.*` is equivalent to `s.find(X) != npos`.
    
    - Remove `src/runtime/regex.{h,cc}` and the Python
    `tvm.runtime.regex_match`
      global registration.
    - Add file-local `contains` / `contains_any` helpers in
    `dnnl_json_runtime.cc`
      and inline `std::string::find` at the 15 call sites.
    - Drop the dead `regex.h` include from
    `src/relax/transform/update_param_struct_info.cc`.
    
    No CMakeLists.txt change needed — `src/runtime/*.cc` is picked up by
    glob.
    
    `USE_DNNL` is OFF in the ci_gpu container, so DNNL-specific runtime
    tests
    are not exercised locally. The DNNL translation unit compiles cleanly
    with
    the inlined helpers, and the full TVM build (636 targets) passes.
---
 python/tvm/runtime/__init__.py                  |  1 -
 python/tvm/runtime/support.py                   | 51 -------------------
 src/relax/transform/update_param_struct_info.cc |  1 -
 src/runtime/contrib/dnnl/dnnl_json_runtime.cc   | 60 +++++++++-------------
 src/runtime/regex.cc                            | 43 ----------------
 src/runtime/regex.h                             | 67 -------------------------
 6 files changed, 25 insertions(+), 198 deletions(-)

diff --git a/python/tvm/runtime/__init__.py b/python/tvm/runtime/__init__.py
index 67839fed02..ee5f3e1dd4 100644
--- a/python/tvm/runtime/__init__.py
+++ b/python/tvm/runtime/__init__.py
@@ -51,5 +51,4 @@ except (ImportError, ValueError):
     # Make the disco module optional.
     disco = None  # type: ignore[assignment]
 
-from .support import _regex_match
 from tvm_ffi import Shape as ShapeTuple
diff --git a/python/tvm/runtime/support.py b/python/tvm/runtime/support.py
index f6591b2871..d9762ef571 100644
--- a/python/tvm/runtime/support.py
+++ b/python/tvm/runtime/support.py
@@ -17,59 +17,8 @@
 
 """Runtime support infra of TVM."""
 
-import re
 from typing import TypeVar
 
-import tvm_ffi
-
-
-@tvm_ffi.register_global_func("tvm.runtime.regex_match")
-def _regex_match(regex_pattern: str, match_against: str) -> bool:
-    """Check if a pattern matches a regular expression
-
-    This function should be used instead of `std::regex` within C++
-    call sites, to avoid ABI incompatibilities with pytorch.
-
-    Currently, the pytorch wheels available through pip install use
-    the pre-C++11 ABI by setting `-DUSE_CXX11_ABI=0` [0]. If TVM were to
-    user the pre-C++11 ABI, this would cause breakages with
-    dynamically-linked LLVM environments.
-
-    Use of the `<regex>` header in TVM should be avoided, as its
-    implementation is not supported by gcc's dual ABI. This ABI
-    incompatibility results in runtime errors either when `std::regex`
-    is called from TVM, or when `std::regex` is called from pytorch,
-    depending on which library was loaded first.  This restriction can
-    be removed when a version of pytorch compiled using
-    `-DUSE_CXX11_ABI=1` is available from PyPI.
-
-    This is exposed as part of `libtvm_runtime.so` as it is used by
-    the DNNL runtime.
-
-    [0] https://github.com/pytorch/pytorch/issues/51039
-
-    Parameters
-    ----------
-    regex_pattern: str
-
-         The regular expression
-
-    match_against: str
-
-        The string against which to match the regular expression
-
-    Returns
-    -------
-    match_result: bool
-
-        True if `match_against` matches the pattern defined by
-        `regex_pattern`, and False otherwise.
-
-    """
-    match = re.match(regex_pattern, match_against)
-    return match is not None
-
-
 T = TypeVar("T")
 
 
diff --git a/src/relax/transform/update_param_struct_info.cc 
b/src/relax/transform/update_param_struct_info.cc
index 02b2c70b7f..031a552a00 100644
--- a/src/relax/transform/update_param_struct_info.cc
+++ b/src/relax/transform/update_param_struct_info.cc
@@ -32,7 +32,6 @@
 #include <unordered_map>
 #include <vector>
 
-#include "../../runtime/regex.h"
 #include "utils.h"
 
 namespace tvm {
diff --git a/src/runtime/contrib/dnnl/dnnl_json_runtime.cc 
b/src/runtime/contrib/dnnl/dnnl_json_runtime.cc
index 2b07b6f9e5..a6440952cd 100644
--- a/src/runtime/contrib/dnnl/dnnl_json_runtime.cc
+++ b/src/runtime/contrib/dnnl/dnnl_json_runtime.cc
@@ -31,7 +31,6 @@
 #include <string>
 #include <vector>
 
-#include "../../../runtime/regex.h"
 #include "../json/json_node.h"
 #include "../json/json_runtime.h"
 
@@ -49,6 +48,16 @@ namespace contrib {
 using namespace tvm::runtime;
 using namespace tvm::runtime::json;
 
+namespace {
+inline bool contains(const std::string& s, const std::string& sub) {
+  return s.find(sub) != std::string::npos;
+}
+template <typename... Args>
+inline bool contains_any(const std::string& s, const Args&... args) {
+  return (contains(s, args) || ...);
+}
+}  // namespace
+
 class DNNLJSONRuntime : public JSONRuntimeBase {
  public:
   DNNLJSONRuntime(const std::string& symbol_name, const std::string& 
graph_json,
@@ -189,46 +198,35 @@ class DNNLJSONRuntime : public JSONRuntimeBase {
 
     if (o_scl_tr || activation[0] != "none" || sum_scl_tr || dst_zp_tr) return 
attr;
 
-    // Define RegExp.
-    std::string bias_add_pat(".*_bias.*");
-    std::string relu_pat(".*_relu.*");
-    std::string tanh_pat(".*_tanh.*");
-    std::string sigmoid_pat(".*_sigmoid.*");
-    std::string clip_pat(".*_clip.*");
-    std::string gelu_pat(".*_gelu.*");
-    std::string swish_pat(".*_swish.*");
-    std::string sum_pat(".*_sum.*");
-    std::string mish_pat(".*_mish.*");
-
     // parsing of name to extract attributes
     auto op_name = nodes_[nid].GetOpName();
 
     // Parsing post-ops.
     dnnl::post_ops ops;
-    if (tvm::runtime::regex_match(op_name, sum_pat)) {
+    if (contains(op_name, "_sum")) {
       ops.append_sum(1.f);
     }
-    if (tvm::runtime::regex_match(op_name, relu_pat)) {
+    if (contains(op_name, "_relu")) {
       ops.append_eltwise(1.f, dnnl::algorithm::eltwise_relu, 0.f, 0.f);
     }
-    if (tvm::runtime::regex_match(op_name, tanh_pat)) {
+    if (contains(op_name, "_tanh")) {
       ops.append_eltwise(1.f, dnnl::algorithm::eltwise_tanh, 0.f, 0.f);
     }
-    if (tvm::runtime::regex_match(op_name, clip_pat)) {
+    if (contains(op_name, "_clip")) {
       float a_min = GetNodeAttr<float>(nodes_[nid], "a_min");
       float a_max = GetNodeAttr<float>(nodes_[nid], "a_max");
       ops.append_eltwise(1.f, dnnl::algorithm::eltwise_clip, a_min, a_max);
     }
-    if (tvm::runtime::regex_match(op_name, sigmoid_pat)) {
+    if (contains(op_name, "_sigmoid")) {
       ops.append_eltwise(1.f, dnnl::algorithm::eltwise_logistic, 0.f, 0.f);
     }
-    if (tvm::runtime::regex_match(op_name, swish_pat)) {
+    if (contains(op_name, "_swish")) {
       ops.append_eltwise(1.f, dnnl::algorithm::eltwise_swish, 1.f, 1.f);
     }
-    if (tvm::runtime::regex_match(op_name, gelu_pat)) {
+    if (contains(op_name, "_gelu")) {
       ops.append_eltwise(1.f, dnnl::algorithm::eltwise_gelu_erf, 0.f, 0.f);
     }
-    if (tvm::runtime::regex_match(op_name, mish_pat)) {
+    if (contains(op_name, "_mish")) {
       ops.append_eltwise(1.f, dnnl::algorithm::eltwise_mish, 1.f, 0.f);
     }
     if (ops.len() != 0) {
@@ -236,8 +234,7 @@ class DNNLJSONRuntime : public JSONRuntimeBase {
     }
 
     // Parsing bias_add.
-    *bias_tr =
-        tvm::runtime::regex_match(op_name, bias_add_pat) ? GetInput(nid, 2) : 
TensorRequisite{};
+    *bias_tr = contains(op_name, "_bias") ? GetInput(nid, 2) : 
TensorRequisite{};
 
     return attr;
   }
@@ -250,31 +247,24 @@ class DNNLJSONRuntime : public JSONRuntimeBase {
     std::set<uint32_t> io_eid_set(run_arg_eid_.begin(), run_arg_eid_.end());
     tensor_registry_ = TensorRegistry(engine_, io_eid_set);
 
-    std::string conv_pat(".*conv[1-3]d.*");
-    std::string deconv_pat(".*deconv[1-3]d.*");
-    std::string conv_transpose_pat(".*conv[1-3]d_transpose.*");
-    std::string dense_pat(".*dense.*");
-    std::string max_pool_pat(".*max_pool[1-3]d");
-    std::string avg_pool_pat(".*avg_pool[1-3]d");
-
     // Build subgraph engine.
     for (size_t nid = 0; nid < nodes_.size(); ++nid) {
       const auto& node = nodes_[nid];
       if (node.GetOpType() == "kernel") {
         TVM_FFI_ICHECK_EQ(node.GetOpType(), "kernel");
         auto op_name = node.GetOpName();
-        if (tvm::runtime::regex_match(op_name, deconv_pat) ||
-            tvm::runtime::regex_match(op_name, conv_transpose_pat)) {
+        if (contains_any(op_name, "deconv1d", "deconv2d", "deconv3d", 
"conv1d_transpose",
+                         "conv2d_transpose", "conv3d_transpose")) {
           Deconvolution(nid);
-        } else if (tvm::runtime::regex_match(op_name, conv_pat)) {
+        } else if (contains_any(op_name, "conv1d", "conv2d", "conv3d")) {
           Convolution(nid);
-        } else if (tvm::runtime::regex_match(op_name, dense_pat)) {
+        } else if (contains(op_name, "dense")) {
           Dense(nid);
         } else if ("nn.batch_norm" == op_name) {
           BatchNorm(nid);
-        } else if (tvm::runtime::regex_match(op_name, max_pool_pat)) {
+        } else if (contains_any(op_name, "max_pool1d", "max_pool2d", 
"max_pool3d")) {
           Pooling(nid, dnnl::algorithm::pooling_max);
-        } else if (tvm::runtime::regex_match(op_name, avg_pool_pat)) {
+        } else if (contains_any(op_name, "avg_pool1d", "avg_pool2d", 
"avg_pool3d")) {
           Pooling(nid, dnnl::algorithm::pooling_avg);
         } else if (elt_name2algo.count(op_name)) {
           Eltwise(nid);
diff --git a/src/runtime/regex.cc b/src/runtime/regex.cc
deleted file mode 100644
index a91bf479ce..0000000000
--- a/src/runtime/regex.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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 src/runtime/regex.cc
- * \brief Exposes calls to python's `re` library.
- */
-
-#include "./regex.h"
-
-#include <tvm/ffi/function.h>
-
-namespace tvm {
-namespace runtime {
-
-bool regex_match(const std::string& match_against, const std::string& 
regex_pattern) {
-  const auto regex_match_func = 
tvm::ffi::Function::GetGlobal("tvm.runtime.regex_match");
-  if (!regex_match_func.has_value()) {
-    TVM_FFI_THROW(RuntimeError)
-        << "The ffi::Function 'tvm.runtime.regex_match' has not been 
registered.  "
-        << "This can occur if the TVM Python library has not yet been 
imported.";
-  }
-  return (*regex_match_func)(regex_pattern, match_against).cast<bool>();
-}
-
-}  // namespace runtime
-}  // namespace tvm
diff --git a/src/runtime/regex.h b/src/runtime/regex.h
deleted file mode 100644
index d8a62e72d3..0000000000
--- a/src/runtime/regex.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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 regex.h
- * \brief Exposes calls to python's `re` library.
- */
-#ifndef TVM_RUNTIME_REGEX_H_
-#define TVM_RUNTIME_REGEX_H_
-
-#include <tvm/runtime/base.h>
-
-#include <string>
-
-namespace tvm {
-namespace runtime {
-
-/* \brief Check if a pattern matches a regular expression
- *
- * This function should be used instead of `std::regex` within C++
- * call sites, to avoid ABI incompatibilities with pytorch.
- *
- * Currently, the pytorch wheels available through pip install use
- * the pre-C++11 ABI by setting `-DUSE_CXX11_ABI=0` [0]. If TVM were to
- * user the pre-C++11 ABI, this would cause breakages with
- * dynamically-linked LLVM environments.
- *
- * Use of the `<regex>` header in TVM should be avoided, as its
- * implementation is not supported by gcc's dual ABI. This ABI
- * incompatibility results in runtime errors either when `std::regex`
- * is called from TVM, or when `std::regex` is called from pytorch,
- * depending on which library was loaded first.  This restriction can
- * be removed when a version of pytorch compiled using
- * `-DUSE_CXX11_ABI=1` is available from PyPI.
- *
- * [0] https://github.com/pytorch/pytorch/issues/51039
- *
- * \param match_against The string against which to match the regular 
expression
- *
- * \param regex_pattern The regular expression
- *
- * \returns match_result True if `match_against` matches the pattern
- *     defined by `regex_pattern`, and False otherwise.
- */
-
-TVM_RUNTIME_DLL bool regex_match(const std::string& match_against,
-                                 const std::string& regex_pattern);
-
-}  // namespace runtime
-}  // namespace tvm
-#endif  // TVM_RUNTIME_REGEX_H_

Reply via email to