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 ee2b3a4ce [FIX] Reject unsupported CUDA vector expressions during 
codegen (#84)
ee2b3a4ce is described below

commit ee2b3a4ce350ef707b064c88afdc81c9a1295f6f
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Oct 26 09:56:34 2026 -0400

    [FIX] Reject unsupported CUDA vector expressions during codegen (#84)
    
    CUDA codegen now reports unsupported vector types, broadcast
    constructors and operators before handing source to nvcc. The checks
    stay at the existing emitters and preserve supported packed storage,
    casts and arithmetic paths. Adds one focused regression for unsupported
    FP8 vector addition.
---
 src/backend/cuda/codegen/codegen_cuda.cc | 33 +++++++++++++++++++++++++++-----
 src/backend/cuda/codegen/codegen_cuda.h  |  1 +
 tests/python/tirx/codegen/test_cuda.py   | 15 +++++++++++++++
 3 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/src/backend/cuda/codegen/codegen_cuda.cc 
b/src/backend/cuda/codegen/codegen_cuda.cc
index f0227c604..366aa0d52 100644
--- a/src/backend/cuda/codegen/codegen_cuda.cc
+++ b/src/backend/cuda/codegen/codegen_cuda.cc
@@ -575,7 +575,7 @@ void CodeGenCUDA::PrintType(const PrimType& t, 
std::ostream& os) {  // NOLINT(*)
     } else {
       fail = true;
     }
-    return;
+    if (!fail) return;
   } else if (IsFloat4(t)) {
     codegen_tags_.insert("fp4");
     if (lanes <= 4) {
@@ -583,7 +583,7 @@ void CodeGenCUDA::PrintType(const PrimType& t, 
std::ostream& os) {  // NOLINT(*)
     } else {
       fail = true;
     }
-    return;
+    if (!fail) return;
   } else if (t == PrimType::Bool()) {
     os << "bool";
     return;
@@ -731,8 +731,11 @@ void CodeGenCUDA::PrintType(const PrimType& t, 
std::ostream& os) {  // NOLINT(*)
           os << "longlong3";
         } else if (lanes == 4) {
           os << "longlong4";
+        } else {
+          fail = true;
         }
-        return;
+        if (!fail) return;
+        break;
       }
 
       default:
@@ -747,7 +750,7 @@ void CodeGenCUDA::PrintType(const PrimType& t, 
std::ostream& os) {  // NOLINT(*)
       return;
     }
   }
-  TVM_FFI_THROW(InternalError) << "Cannot convert type " << t << " to CUDA 
type";
+  TVM_FFI_THROW(RuntimeError) << "CUDA codegen does not support type " << 
t->dtype;
 }
 
 void CodeGenCUDA::PrintVecConstructor(const PrimType& t, std::ostream& os) {
@@ -845,6 +848,10 @@ void CodeGenCUDA::PrintVecBinaryOpNanPreserving(const 
std::string& op, const Pri
 
 void CodeGenCUDA::PrintVecBinaryOp(const std::string& op, const PrimType& t, 
PrimExpr lhs,
                                    PrimExpr rhs, std::ostream& os) {  // 
NOLINT(*)
+  if (IsFloat8(lhs.ty())) {
+    TVM_FFI_THROW(RuntimeError) << "CUDA codegen does not support '" << op << 
"' for "
+                                << lhs.ty()->dtype;
+  }
   // Declare the result.
   std::string sret = name_supply_->FreshName("_");
   this->PrintIndent();
@@ -1516,6 +1523,17 @@ void CodeGenCUDA::Dispatch_(const prim::RampObj* op, 
std::ostream& os) {
   os << sret;
 }
 
+void CodeGenCUDA::Dispatch_(const prim::BitwiseNotObj* op, std::ostream& os) {
+  PrimType t = op->a.ty();
+  // Packed integers represented by a scalar still support the C bitwise 
operator.
+  bool packed_scalar = ((t.bits() == 1 || t.bits() == 4) && t.bits() * 
t.lanes() <= 32) ||
+                       (t.bits() == 8 && t.lanes() == 4);
+  if (t.lanes() > 1 && !t.MatchesCode(DLDataTypeCode::kDLBool) && 
!packed_scalar) {
+    TVM_FFI_THROW(RuntimeError) << "CUDA codegen does not support '~' for " << 
t->dtype;
+  }
+  CodeGenC::Dispatch_(op, os);
+}
+
 void CodeGenCUDA::Dispatch_(const prim::BroadcastObj* op, std::ostream& os) {  
// NOLINT(*)
   PrimType op_ty = op->ty.as_or_throw<PrimType>();
   int lanes = op_ty.lanes();
@@ -1574,7 +1592,9 @@ void CodeGenCUDA::Dispatch_(const prim::BroadcastObj* op, 
std::ostream& os) {  /
   }
 
   if (IsFloat8(op_ty) || IsFloat4(op_ty)) {
-    TVM_FFI_ICHECK(lanes == 1 || lanes == 2 || lanes == 4);
+    if (lanes != 2 && lanes != 4) {
+      TVM_FFI_THROW(RuntimeError) << "CUDA codegen does not support Broadcast 
for " << op_ty->dtype;
+    }
     std::string v = PrintExprToSSA(op->value);
     // Implicit conversion from float back to fp8
     PrintType(op_ty, os);
@@ -1631,6 +1651,9 @@ void CodeGenCUDA::Dispatch_(const prim::BroadcastObj* op, 
std::ostream& os) {  /
     }
   }
 
+  if (lanes > 4) {
+    TVM_FFI_THROW(RuntimeError) << "CUDA codegen does not support Broadcast 
for " << op_ty->dtype;
+  }
   std::string v = PrintExprToSSA(op->value);
   PrintVecConstructor(op_ty, os);
   os << '(';
diff --git a/src/backend/cuda/codegen/codegen_cuda.h 
b/src/backend/cuda/codegen/codegen_cuda.h
index e502d3c0f..d09496e22 100644
--- a/src/backend/cuda/codegen/codegen_cuda.h
+++ b/src/backend/cuda/codegen/codegen_cuda.h
@@ -86,6 +86,7 @@ class CodeGenCUDA final : public CodeGenC {
   void Dispatch_(const FloatImmObj* op, std::ostream& os) final;
   void Dispatch_(const CallObj* op, std::ostream& os) final;
   void Dispatch_(const prim::CastObj* op, std::ostream& os) final;
+  void Dispatch_(const prim::BitwiseNotObj* op, std::ostream& os) final;
   void Dispatch_(const prim::MinObj* op, std::ostream& os) final;  // NOLINT(*)
   void Dispatch_(const prim::MaxObj* op, std::ostream& os) final;  // NOLINT(*)
   template <typename T>
diff --git a/tests/python/tirx/codegen/test_cuda.py 
b/tests/python/tirx/codegen/test_cuda.py
index 751a8ff6a..9aabca3d4 100644
--- a/tests/python/tirx/codegen/test_cuda.py
+++ b/tests/python/tirx/codegen/test_cuda.py
@@ -72,6 +72,21 @@ def test_isnan_scalar_and_vector_codegen(dtype):
     assert "!=" in source
 
 
+def test_unsupported_fp8_vector_arithmetic(monkeypatch):
+    # Source-only codegen must reject the operation before invoking nvcc.
+    monkeypatch.setenv("TVM_TIRX_COMPILE_FORCE_FALLBACK", "1")
+
+    @T.function
+    def func(A: T.Tensor((1,), "float8_e5m2x2"), B: T.Tensor((1,), 
"float8_e5m2x2")):
+        T.device_entry(launch=T.cuda.LaunchConfig(grid=1, block=1))
+        B[0] = A[0] + A[0]
+
+    with pytest.raises(
+        RuntimeError, match=re.escape("CUDA codegen does not support '+' for 
float8_e5m2x2")
+    ):
+        _get_source(func)
+
+
 def _helper_source(src: str, helper_name: str) -> str:
     pattern = rf"__forceinline__ __device__ [^{{;]+ {re.escape(helper_name)}\("
     match = re.search(pattern, src)

Reply via email to