Extract memcpy wrapper used by Copy operator into a microkernel

PiperOrigin-RevId: 344180743
diff --git a/BUILD.bazel b/BUILD.bazel
index 845637b..5b4802b 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -518,6 +518,7 @@
     "src/x32-zip/x3-scalar.c",
     "src/x32-zip/x4-scalar.c",
     "src/x32-zip/xm-scalar.c",
+    "src/xx-copy/memcpy.c",
 ]
 
 WASM_UKERNELS = [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 201d6b4..205b4ad 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -639,7 +639,8 @@
   src/x32-zip/x2-scalar.c
   src/x32-zip/x3-scalar.c
   src/x32-zip/x4-scalar.c
-  src/x32-zip/xm-scalar.c)
+  src/x32-zip/xm-scalar.c
+  src/xx-copy/memcpy.c)
 
 SET(XNNPACK_PSIMD_ACCMATH_MICROKERNEL_SRCS
   src/qs8-requantization/fp32-psimd.c
diff --git a/src/init.c b/src/init.c
index 4d5fd02..e4757d4 100644
--- a/src/init.c
+++ b/src/init.c
@@ -92,6 +92,13 @@
     }
   #endif
 
+  /**************************** XX micro-kernels ****************************/
+  #ifndef XNN_NO_XX_OPERATORS
+    init_flags |= XNN_INIT_FLAG_XX;
+
+    xnn_params.xx.copy = (xnn_univector_ukernel_function) xnn_xx_copy_ukernel__memcpy;
+  #endif
+
   if (cpuinfo_has_arm_neon()) {
     /**************************** QS8 micro-kernels ****************************/
     #ifndef XNN_NO_QS8_OPERATORS
@@ -734,6 +741,13 @@
 
 #elif XNN_ARCH_ARM64
 
+  /**************************** XX micro-kernels ****************************/
+  #ifndef XNN_NO_XX_OPERATORS
+    init_flags |= XNN_INIT_FLAG_XX;
+
+    xnn_params.xx.copy = (xnn_univector_ukernel_function) xnn_xx_copy_ukernel__memcpy;
+  #endif
+
   /**************************** QS8 micro-kernels ****************************/
   #ifndef XNN_NO_QS8_OPERATORS
     init_flags |= XNN_INIT_FLAG_QS8;
@@ -1367,6 +1381,13 @@
     return;
   }
 
+  /**************************** XX micro-kernels ****************************/
+  #ifndef XNN_NO_XX_OPERATORS
+    init_flags |= XNN_INIT_FLAG_XX;
+
+    xnn_params.xx.copy = (xnn_univector_ukernel_function) xnn_xx_copy_ukernel__memcpy;
+  #endif
+
   /**************************** QS8 micro-kernels ****************************/
   #ifndef XNN_NO_QS8_OPERATORS
     init_flags |= XNN_INIT_FLAG_QS8;
@@ -2013,6 +2034,14 @@
   #endif  // XNN_NO_X32_OPERATORS
 
 #elif XNN_ARCH_WASMSIMD
+
+  /**************************** XX micro-kernels ****************************/
+  #ifndef XNN_NO_XX_OPERATORS
+    init_flags |= XNN_INIT_FLAG_XX;
+
+    xnn_params.xx.copy = (xnn_univector_ukernel_function) xnn_xx_copy_ukernel__memcpy;
+  #endif
+
   /**************************** QS8 micro-kernels ****************************/
   #ifndef XNN_NO_QS8_OPERATORS
     init_flags |= XNN_INIT_FLAG_QS8;
@@ -2523,6 +2552,14 @@
   #endif  // XNN_NO_X32_OPERATORS
 
 #elif XNN_ARCH_WASM
+
+  /**************************** XX micro-kernels ****************************/
+  #ifndef XNN_NO_XX_OPERATORS
+    init_flags |= XNN_INIT_FLAG_XX;
+
+    xnn_params.xx.copy = (xnn_univector_ukernel_function) xnn_xx_copy_ukernel__memcpy;
+  #endif
+
   /**************************** QU8 micro-kernels ****************************/
   #ifndef XNN_NO_QU8_OPERATORS
     init_flags |= XNN_INIT_FLAG_QU8;
diff --git a/src/operators/unary-elementwise-nc.c b/src/operators/unary-elementwise-nc.c
index 027e19e..472f4d6 100644
--- a/src/operators/unary-elementwise-nc.c
+++ b/src/operators/unary-elementwise-nc.c
@@ -263,10 +263,6 @@
     ceiling_op_out);
 }
 
-static void memcpy_ukernel(size_t size, const void* input, void* output, const void* params) {
-  memcpy(output, input, size);
-}
-
 enum xnn_status xnn_create_copy_nc_x32(
     size_t channels,
     size_t input_stride,
@@ -278,7 +274,7 @@
     channels, input_stride, output_stride, flags,
     NULL, 0,
     xnn_operator_type_copy_nc_x32,
-    memcpy_ukernel,
+    xnn_params.xx.copy,
     copy_op_out);
 }
 
diff --git a/src/xnnpack/params.h b/src/xnnpack/params.h
index 085a057..1cd5f53 100644
--- a/src/xnnpack/params.h
+++ b/src/xnnpack/params.h
@@ -1979,12 +1979,17 @@
 #define XNN_INIT_FLAG_U8      0x00000080
 // Indicates that X8 XNNPACK microkernels are available for use.
 #define XNN_INIT_FLAG_X8      0x00000100
+// Indicates that XX XNNPACK microkernels are available for use.
+#define XNN_INIT_FLAG_XX      0x00000200
 
 struct xnn_parameters {
   // Bitwise combination of XNN_INIT_FLAG_* flags
   uint32_t init_flags;
   struct xnn_allocator allocator;
   struct {
+    xnn_univector_ukernel_function copy;
+  } xx;
+  struct {
     struct gemm_parameters gemm;
     struct dwconv_parameters dwconv[XNN_MAX_QS8_DWCONV_UKERNELS];
     struct gavgpool_parameters gavgpool;
diff --git a/src/xnnpack/vunary.h b/src/xnnpack/vunary.h
index c4cbeae..b4442e2 100644
--- a/src/xnnpack/vunary.h
+++ b/src/xnnpack/vunary.h
@@ -599,6 +599,15 @@
 DECLARE_F32_RELU_UKERNEL_FUNCTION(xnn_f32_relu_ukernel__wasm32_shr_x2)
 DECLARE_F32_RELU_UKERNEL_FUNCTION(xnn_f32_relu_ukernel__wasm32_shr_x4)
 
+#define DECLARE_XX_VUNARY_UKERNEL_FUNCTION(fn_name) \
+  XNN_INTERNAL void fn_name(                        \
+      size_t size,                                  \
+      const void* input,                            \
+      void* output,                                 \
+      const void* params);
+
+DECLARE_XX_VUNARY_UKERNEL_FUNCTION(xnn_xx_copy_ukernel__memcpy)
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/src/xx-copy/memcpy.c b/src/xx-copy/memcpy.c
new file mode 100644
index 0000000..d247f99
--- /dev/null
+++ b/src/xx-copy/memcpy.c
@@ -0,0 +1,17 @@
+// Copyright 2020 Google LLC
+//
+// This source code is licensed under the BSD-style license found in the
+// LICENSE file in the root directory of this source tree.
+
+#include <assert.h>
+#include <string.h>
+
+#include <xnnpack/common.h>
+#include <xnnpack/vunary.h>
+
+
+void xnn_xx_copy_ukernel__memcpy(size_t size, const void* input, void* output, const void* params) {
+  assert(size != 0);
+
+  memcpy(output, input, size);
+}