[EmitC] Remove `clearStruct` helper (#18464)

Also don't explicitly zero out refs in the during state initialization
as the whole state struct is zero initialized.

---------
Signed-off-by: Simon Camphausen <simon.camphausen@iml.fraunhofer.de>
Co-authored-by: Marius Brehler <marius.brehler@amd.com>
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
index d103c92..c57802d 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
@@ -45,22 +45,6 @@
   CCONV_ARGUMENT_MODULE_STATE,
 };
 
-/// Create a call to memset to clear a struct
-LogicalResult clearStruct(OpBuilder builder, Value structValue) {
-  auto loc = structValue.getLoc();
-
-  if (auto ptrType =
-          llvm::dyn_cast<emitc::PointerType>(structValue.getType())) {
-    Value sizeValue = emitc_builders::sizeOf(
-        builder, loc, TypeAttr::get(ptrType.getPointee()));
-    emitc_builders::memset(builder, loc, structValue, 0, sizeValue);
-
-    return success();
-  }
-
-  return emitError(loc, "expected pointer type");
-}
-
 LogicalResult convertFuncOp(IREE::VM::FuncOp funcOp,
                             const IREE::VM::EmitCTypeConverter &typeConverter,
                             SmallVector<BlockArgument> &blockArgsToRemove) {
@@ -138,20 +122,15 @@
   builder.setInsertionPointToStart(&entryBlock);
 
   for (int i = 0; i < numLocalRefs; i++) {
-    auto ref = emitc_builders::allocateVariable(
+    auto [ref, refPtr] = emitc_builders::allocZeroInitializedVar(
         builder, loc, emitc::OpaqueType::get(ctx, "iree_vm_ref_t"));
 
-    Value refPtr = emitc_builders::addressOf(builder, loc, ref);
     auto refPtrOp = cast<emitc::ApplyOp>(refPtr.getDefiningOp());
 
     // Cache local refs so that we can release them before a return operation.
     // Here we rely on the fact that the register allocation maps arguments in
     // the first slots.
     funcAnalysis.cacheLocalRef(i + numRefArgs, refPtrOp);
-
-    if (failed(clearStruct(builder, refPtr))) {
-      return failure();
-    }
   }
 
   for (Block &block : llvm::drop_begin(newFuncOp.getBlocks(), 1)) {
@@ -315,15 +294,9 @@
     assert(srcRef.getType() == emitc::PointerType::get(emitc::OpaqueType::get(
                                    ctx, "iree_vm_ref_t")));
 
-    auto tmpRef = emitc_builders::allocateVariable(
+    auto [tmpRef, tmpPtr] = emitc_builders::allocZeroInitializedVar(
         builder, location, emitc::OpaqueType::get(ctx, "iree_vm_ref_t"));
 
-    Value tmpPtr = emitc_builders::addressOf(builder, location, tmpRef);
-
-    if (failed(clearStruct(builder, tmpPtr))) {
-      return failure();
-    }
-
     StringRef callee = isMove ? "iree_vm_ref_move" : "iree_vm_ref_retain";
     builder.create<emitc::CallOpaqueOp>(
         /*location=*/location,
@@ -735,35 +708,6 @@
                                builder.getIndexAttr(2)}));
     }
 
-    // Zero out refs from state struct.
-    auto ordinalCounts = moduleOp.getOrdinalCountsAttr();
-    if (!ordinalCounts) {
-      return moduleOp.emitError()
-             << "ordinal_counts attribute not found. The OrdinalAllocationPass "
-                "must be run before.";
-    }
-    const int numGlobalRefs = ordinalCounts.getGlobalRefs();
-
-    if (numGlobalRefs > 0) {
-      auto refs =
-          cast<TypedValue<emitc::PointerType>>(emitc_builders::structPtrMember(
-              builder, loc,
-              /*type=*/
-              emitc::PointerType::get(
-                  emitc::OpaqueType::get(ctx, "iree_vm_ref_t")),
-              /*memberName=*/"refs",
-              /*operand=*/state));
-
-      for (int i = 0; i < numGlobalRefs; i++) {
-        auto refPtrOp = emitc_builders::arrayElementAddress(
-            builder, loc, /*index=*/i, /*operand=*/refs);
-
-        if (failed(clearStruct(builder, refPtrOp))) {
-          return failure();
-        }
-      }
-    }
-
     auto baseStateOp = builder.create<emitc::CastOp>(
         /*location=*/loc,
         /*type=*/
@@ -2789,15 +2733,9 @@
 
     Value operandRef = this->getModuleAnalysis().lookupRef(operand);
 
-    auto ref = emitc_builders::allocateVariable(
+    auto [ref, refPtr] = emitc_builders::allocZeroInitializedVar(
         builder, loc, emitc::OpaqueType::get(ctx, "iree_vm_ref_t"));
 
-    Value refPtr = emitc_builders::addressOf(builder, loc, ref);
-
-    if (failed(clearStruct(builder, refPtr))) {
-      return failure();
-    }
-
     builder.create<emitc::CallOpaqueOp>(
         /*location=*/loc,
         /*type=*/TypeRange{},
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
index ca7756d..94dbb13 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
@@ -65,6 +65,15 @@
       emitc::OpaqueAttr::get(ctx, initializer.value_or("")));
 }
 
+std::pair<TypedValue<emitc::LValueType>, TypedValue<emitc::PointerType>>
+allocZeroInitializedVar(OpBuilder builder, Location location, Type type) {
+  auto var = allocateVariable(builder, location, type);
+  auto varPtr = addressOf(builder, location, var);
+  auto size = sizeOf(builder, location, TypeAttr::get(type));
+  emitc_builders::memset(builder, location, varPtr, 0, size);
+  return {var, varPtr};
+}
+
 TypedValue<emitc::LValueType> asLValue(OpBuilder builder, Location loc,
                                        Value value) {
   auto var = allocateVariable(builder, loc, value.getType());
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h
index 6a907ee..1f0320b 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h
@@ -53,6 +53,11 @@
 allocateVariable(OpBuilder builder, Location location, Type type,
                  std::optional<StringRef> initializer = std::nullopt);
 
+/// Allocate a new zero initialized variable. This is done through a call to
+/// memset, as all variables are declared without initializer in the emitter.
+std::pair<TypedValue<emitc::LValueType>, TypedValue<emitc::PointerType>>
+allocZeroInitializedVar(OpBuilder builder, Location location, Type type);
+
 /// Convert a value to an EmitC LValue by allocating a new variable and
 /// assigning the operand to it. Note that the variable declaration and
 /// assignment are split into two separate statements, so that padding bytes for