tqchen commented on code in PR #16183:
URL: https://github.com/apache/tvm/pull/16183#discussion_r1409728621


##########
include/tvm/runtime/packed_func.h:
##########
@@ -547,29 +551,43 @@ class TVMPODValue_ {
     // Allow automatic conversion from int to float
     // This avoids errors when user pass in int from
     // the frontend while the API expects a float.
-    if (type_code_ == kDLInt) {
-      return static_cast<double>(value_.v_int64);
+    if (auto opt = TryAsBool()) {
+      return opt.value();
+    } else if (auto opt = TryAsInt()) {

Review Comment:
   We should go in the order of 
   
   - TryAsFloat, TryAsInt, TryAsBool
   
   Prioritize the most likely ones



##########
include/tvm/runtime/packed_func.h:
##########
@@ -627,13 +645,54 @@ class TVMPODValue_ {
   template <typename TObjectRef>
   inline TObjectRef AsObjectRef() const;
 
+  std::optional<int64_t> TryAsInt() const {
+    // Helper function to reduce duplication in the variable integer
+    // conversions.  This is publicly exposed, as it can be useful in
+    // specializations of PackedFuncValueConverter.
+    if (auto opt = FromBoxed<int64_t>()) {

Review Comment:
   Calling convention note: it would be simpler to require that TVMArgValue and 
TVMRetValue always NOT hold Boxed values. This would help to reduce the overall 
cost of the codegen function handling.
   
   That does mean when we assign Boxed Object into TVMArg and TVMRet, they 
should be unboxed. I know that we can make an exception for bool for now until 
we introduce a specific bool POD code.



##########
include/tvm/runtime/packed_func.h:
##########
@@ -2129,6 +2315,42 @@ struct PackedFuncValueConverter<::tvm::runtime::String> {
   }
 };
 
+template <typename T>
+struct PackedFuncValueConverter<Array<T>> {

Review Comment:
   I feel automatic conversion here is a bit overkill.  Recursive automatic 
conversion would be too much overhead whe passing through FFI. The developer 
should ensure the correct typings of the internal contained values
   
   I know it may bring some convenience, but in this case I think we should not 
do it. 
   
   Suggestion: Remove the conversion logic from this PR



##########
include/tvm/runtime/packed_func.h:
##########
@@ -547,29 +551,43 @@ class TVMPODValue_ {
     // Allow automatic conversion from int to float
     // This avoids errors when user pass in int from
     // the frontend while the API expects a float.
-    if (type_code_ == kDLInt) {
-      return static_cast<double>(value_.v_int64);
+    if (auto opt = TryAsBool()) {
+      return opt.value();
+    } else if (auto opt = TryAsInt()) {
+      return opt.value();
+    } else if (auto opt = TryAsFloat()) {
+      return opt.value();
+    } else {
+      LOG(FATAL) << TVM_LOG_INCORRECT_TYPE_CODE(type_code_, kDLFloat);
     }
-    TVM_CHECK_TYPE_CODE(type_code_, kDLFloat);
-    return value_.v_float64;
   }
   operator int64_t() const {
-    TVM_CHECK_TYPE_CODE(type_code_, kDLInt);
-    return value_.v_int64;
-  }
-  operator uint64_t() const {
-    TVM_CHECK_TYPE_CODE(type_code_, kDLInt);
-    return value_.v_int64;
+    if (auto opt = TryAsBool()) {

Review Comment:
   We should go in the order of
   
   TryAsInt, TryAsBool
   Prioritize the most likely ones



##########
include/tvm/runtime/packed_func.h:
##########
@@ -627,13 +645,54 @@ class TVMPODValue_ {
   template <typename TObjectRef>
   inline TObjectRef AsObjectRef() const;
 
+  std::optional<int64_t> TryAsInt() const {
+    // Helper function to reduce duplication in the variable integer
+    // conversions.  This is publicly exposed, as it can be useful in
+    // specializations of PackedFuncValueConverter.
+    if (auto opt = FromBoxed<int64_t>()) {
+      return opt.value();
+    } else if (type_code_ == kDLInt) {
+      return value_.v_int64;
+    } else {
+      return std::nullopt;
+    }
+  }
+
+  std::optional<double> TryAsFloat() const {
+    // Helper function to reduce duplication in the variable integer
+    // conversions.  This is publicly exposed, as it can be useful in
+    // specializations of PackedFuncValueConverter.
+    if (auto opt = FromBoxed<double>()) {

Review Comment:
   Calling convention note: it would be simpler to require that TVMArgValue and 
TVMRetValue always NOT hold Boxed values. This would help to reduce the overall 
cost of the codegen function handling.
   
   That does mean when we assign Boxed Object into TVMArg and TVMRet, they 
should be unboxed. I know that we can make an exception for bool for now until 
we introduce a specific bool POD code.



##########
include/tvm/runtime/packed_func.h:
##########
@@ -2035,46 +2167,100 @@ inline TObjectRef TVMPODValue_::AsObjectRef() const {
     ICHECK(!checked_type.defined()) << "Expected " << 
ObjectTypeChecker<TObjectRef>::TypeName()
                                     << ", but got " << checked_type.value();
     return TObjectRef(GetObjectPtr<Object>(ptr));
-  } else if (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
-             type_code_ == kTVMNDArrayHandle) {
-    // Casting to a base class that NDArray can sub-class
-    ObjectPtr<Object> data =
-        
NDArray::FFIDataFromHandle(static_cast<TVMArrayHandle>(value_.v_handle));
-    return TObjectRef(data);
-  } else if (std::is_base_of<ContainerType, Module::ContainerType>::value &&
-             type_code_ == kTVMModuleHandle) {
-    // Casting to a base class that Module can sub-class
-    return 
TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
-  } else if (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value 
&&
-             type_code_ == kTVMPackedFuncHandle) {
-    // Casting to a base class that PackedFunc can sub-class
-    return 
TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
-  } else {
-    TVM_CHECK_TYPE_CODE(type_code_, kTVMObjectHandle);
-    return TObjectRef(ObjectPtr<Object>(nullptr));
   }
+
+  if constexpr (std::is_base_of_v<ContainerType, NDArray::ContainerType>) {
+    if (type_code_ == kTVMNDArrayHandle) {
+      // Casting to a base class that NDArray can sub-class
+      ObjectPtr<Object> data =
+          
NDArray::FFIDataFromHandle(static_cast<TVMArrayHandle>(value_.v_handle));
+      return TObjectRef(data);
+    }
+  }
+
+  if constexpr (std::is_base_of_v<ContainerType, Module::ContainerType>) {
+    if (type_code_ == kTVMModuleHandle) {
+      // Casting to a base class that Module can sub-class
+      return 
TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
+    }
+  }
+
+  if constexpr (std::is_base_of_v<ContainerType, PackedFunc::ContainerType>) {
+    if (type_code_ == kTVMPackedFuncHandle) {
+      // Casting to a base class that PackedFunc can sub-class
+      return 
TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
+    }
+  }
+
+  if constexpr (std::is_base_of_v<TObjectRef, BoxInt>) {
+    if (type_code_ == kTVMArgInt) {
+      return BoxInt(value_.v_int64);
+    }
+  }
+
+  if constexpr (std::is_base_of_v<TObjectRef, BoxFloat>) {
+    if (type_code_ == kTVMArgFloat) {
+      return BoxFloat(value_.v_float64);
+    }
+  }
+
+  if constexpr (std::is_base_of_v<TObjectRef, String>) {
+    if (type_code_ == kTVMStr) {
+      return String(value_.v_str);
+    }
+  }
+
+  TVM_CHECK_TYPE_CODE(type_code_, kTVMObjectHandle);
+  return TObjectRef(ObjectPtr<Object>(nullptr));
 }
 
 template <typename TObjectRef, typename>
 inline TVMRetValue& TVMRetValue::operator=(TObjectRef other) {
   using ContainerType = typename TObjectRef::ContainerType;
   const Object* ptr = other.get();
-  if (ptr != nullptr) {
-    if (std::is_base_of<NDArray::ContainerType, ContainerType>::value ||
-        (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
-         ptr->IsInstance<NDArray::ContainerType>())) {
+
+  if constexpr (std::is_base_of_v<ContainerType, NDArray::ContainerType> ||
+                std::is_base_of_v<NDArray::ContainerType, ContainerType>) {
+    if (ptr && (std::is_base_of_v<NDArray::ContainerType, ContainerType> ||

Review Comment:
   nit: would be nice to keep the originals tructure of `if (ptr != nullptr)`, 
they  helps to keep the structure of the code, lift out a CSE and also makes 
the diff more readable



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to