diff --git a/examples/array_sum/main.c b/examples/array_sum/main.c
index 29951267aa1f84c0163a964bc3912a9bb7a898a5..80a40003ff47de4adcac4320ed29df4b8ae02d15 100644
--- a/examples/array_sum/main.c
+++ b/examples/array_sum/main.c
@@ -34,11 +34,11 @@ int main(int argc, char * argv[])
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,17,
     };
-    T out = 0;
-    struct fmpi_task array_sum_task = FMPI_TASK_REGISTER(
+    T out;
+        struct fmpi_task array_sum_task = FMPI_TASK_REGISTER(
         ctx, fut_array_sum,
-        fmpi_data_1d(ctx, &out, 1),
-        fmpi_data_1d(ctx, in, 64),
+        fmpi_data_1d_out(ctx, &out, 1),
+        fmpi_data_1d_in_new(ctx, in, 64),
     );
     fmpi_task_run(ctx, &array_sum_task);
     if(fmpi_is_root(ctx)) {
diff --git a/include/fmpi_data.h b/include/fmpi_data.h
index f0e23cf50fa34123e1ca4c35860e8e66690f63ea..68724925c7a91893c1d1bfeb3b7bc0468b5e712e 100644
--- a/include/fmpi_data.h
+++ b/include/fmpi_data.h
@@ -72,8 +72,14 @@ typedef struct fmpi_data {
  *  TODO
  * }
  */
-#define fmpi_data_1d(ctx, data, x) \
-    FMPI_DATA_FUNC(data_1d, ctx, data, x, 0, 0)
+#define fmpi_data_1d_in(ctx, data, x) \
+    FMPI_DATA_FUNC(data_1d_in, ctx, data, x, 1, 1)
+
+#define fmpi_data_1d_in_new(ctx, data, x) \
+    FMPI_DATA_FUNC(data_1d_in_new, ctx, data, x, 1, 1)
+
+#define fmpi_data_1d_out(ctx, data, x) \
+    FMPI_DATA_FUNC(data_1d_out, ctx, data, x, 1, 1)
 /*------------------------------------------------------------------------------
     fmpi_data_2d()
 ------------------------------------------------------------------------------*/
@@ -92,8 +98,14 @@ typedef struct fmpi_data {
  *  TODO
  * }
  */
-#define fmpi_data_2d(ctx, data, x, y) \
-    FMPI_DATA_FUNC(data_2d, ctx, data, x, y, 0)
+#define fmpi_data_2d_in(ctx, data, x, y) \
+    FMPI_DATA_FUNC(data_2d_in, ctx, data, x, y, 1)
+
+#define fmpi_data_2d_in_new(ctx, data, x, y) \
+    FMPI_DATA_FUNC(data_1d_in_new, ctx, data, x, y, 1)
+
+#define fmpi_data_2d_out(ctx, data, x, y) \
+    FMPI_DATA_FUNC(data_2d_out, ctx, data, x, y, 1)
 /*------------------------------------------------------------------------------
     fmpi_data_3d()
 ------------------------------------------------------------------------------*/
@@ -113,8 +125,14 @@ typedef struct fmpi_data {
  *  TODO
  * }
  */
-#define fmpi_data_3d(ctx, data, x, y, z) \
-    FMPI_DATA_FUNC(data_3d, ctx, data, x, y, z)
+#define fmpi_data_3d_in(ctx, data, x, y, z) \
+    FMPI_DATA_FUNC(data_3d_in, ctx, data, x, y, z)
+
+#define fmpi_data_3d_in_new(ctx, data, x, y, z) \
+    FMPI_DATA_FUNC(data_3d_in_new, ctx, data, x, y, z)
+
+#define fmpi_data_3d_out(ctx, data, x, y, z) \
+    FMPI_DATA_FUNC(data_3d_out, ctx, data, x, y, z)
 /*==============================================================================
     GUARD
 ==============================================================================*/
diff --git a/include/internal/generic/fmpi_data_generic.h b/include/internal/generic/fmpi_data_generic.h
index 16b230280c03bb66a6b9da5d8e00383f851ae021..5bfdb9e5b18be47726fe488b00b07afa0db84b30 100644
--- a/include/internal/generic/fmpi_data_generic.h
+++ b/include/internal/generic/fmpi_data_generic.h
@@ -40,9 +40,15 @@ struct fmpi_ctx;
 
 #define FMPI_DATA_FUNC(func, ctx, data, x, y, z) \
     FMPI_GENERIC_FUNC(data, func, FMPI_DATA_TYPES)(ctx, data, x, y, z)
-    
+
 #define FMPI_DATA_DECLARATION(D, T) \
-struct fmpi_data fmpi_data_##D##d_##T( \
+struct fmpi_data fmpi_data_##D##d_in_##T( \
+    const struct fmpi_ctx * ctx, T * data, size_t x, size_t y, size_t z \
+);\
+struct fmpi_data fmpi_data_##D##d_in_new_##T( \
+    const struct fmpi_ctx * ctx, T * data, size_t x, size_t y, size_t z \
+);\
+struct fmpi_data fmpi_data_##D##d_out_##T( \
     const struct fmpi_ctx * ctx, T * data, size_t x, size_t y, size_t z \
 )
 
diff --git a/src/fmpi_data.c b/src/fmpi_data.c
index ef76bbf58f841832849d9337ce6bad3dcccb9ff8..217cf6634d47b2c7bb00a875194a7bf97fa0a378 100644
--- a/src/fmpi_data.c
+++ b/src/fmpi_data.c
@@ -26,42 +26,59 @@
 // C Standard Library
 #include <assert.h>
 #include <stddef.h> // NULL, size_t
+#include <stdio.h>  // fprintf()
+#include <stdlib.h> // malloc()
 // Internal
 #include "internal/fmpi_futhark.h"
 #include "internal/generic/fmpi_type.h"
-/*==============================================================================
-    PRIVATE FUNCTION DECLARATION
-==============================================================================*/
-static struct fmpi_data fmpi_data_create(
-    void * data, enum fmpi_type type, size_t dims_cnt, size_t x, size_t y, size_t z
-);
 /*==============================================================================
     PUBLIC FUNCTION DEFINITION
 ==============================================================================*/
 #define FMPI_DATA_DEFINITION(D, T) \
-struct fmpi_data fmpi_data_##D##d_##T( \
-    const struct fmpi_ctx * const ctx, T * const data, const size_t x, const size_t y, const size_t z \
+struct fmpi_data fmpi_data_##D##d_in_##T( \
+    const struct fmpi_ctx * const ctx, T * const data, \
+    const size_t x, const size_t y, const size_t z \
 ){ \
+    assert(ctx != NULL); \
     assert(data != NULL); \
-    return fmpi_data_create(data, FMPI_TYPE_##T, D, x, y, z); \
+    _Static_assert(D <= 3, ""); \
+    return (struct fmpi_data){ \
+        .type = FMPI_TYPE_##T, \
+        .dims_length = {x, y, z}, \
+        .dims_cnt = D, \
+        .start = data \
+    }; \
+} \
+struct fmpi_data fmpi_data_##D##d_in_new_##T( \
+    const struct fmpi_ctx * const ctx, T * const data, \
+    const size_t x, const size_t y, const size_t z \
+){ \
+    assert(ctx != NULL); \
+    assert(data != NULL); \
+    _Static_assert(D <= 3, ""); \
+    struct futhark_##T##_##D##d * const start = fmpi_futhark_new_##D##d_##T(ctx, data, x, y, z); \
+    return (struct fmpi_data){ \
+        .type = FMPI_TYPE_##T, \
+        .dims_length = {x, y, z}, \
+        .dims_cnt = D, \
+        .start = start \
+    }; \
+} \
+struct fmpi_data fmpi_data_##D##d_out_##T( \
+    const struct fmpi_ctx * const ctx, T * const data, \
+    const size_t x, const size_t y, const size_t z \
+){ \
+    assert(ctx != NULL); \
+    assert(data != NULL); \
+    _Static_assert(D <= 3, ""); \
+    return (struct fmpi_data){ \
+        .type = FMPI_TYPE_##T, \
+        .dims_length = {x, y, z}, \
+        .dims_cnt = D, \
+        .start = data \
+    }; \
 }
 
 FMPI_DEFINE_DIM_FUNCS(FMPI_DATA_DEFINITION, 1, FMPI_DATA_TYPES)
 FMPI_DEFINE_DIM_FUNCS(FMPI_DATA_DEFINITION, 2, FMPI_DATA_TYPES)
 FMPI_DEFINE_DIM_FUNCS(FMPI_DATA_DEFINITION, 3, FMPI_DATA_TYPES)
-/*==============================================================================
-    PRIVATE FUNCTION DEFINITION
-==============================================================================*/
-static struct fmpi_data fmpi_data_create(
-    void * const data, const enum fmpi_type type, const size_t dims_cnt,
-    const size_t x, const size_t y, const size_t z
-){
-    assert(data != NULL);
-    assert(dims_cnt >= 0 && dims_cnt <= 3);
-    return (struct fmpi_data){
-        .type = type,
-        .dims_length = {x, y, z},
-        .dims_cnt = dims_cnt,
-        .start = data
-    };
-}