diff --git a/Cargo.lock b/Cargo.lock
index 4a9b889119f59ef0097453a9d22a3caef39ac7bc..ffb61f4d8beb387ba3c756617f5bb3c8ce18ef3b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1209,6 +1209,16 @@ dependencies = [
  "with_builtin_macros",
 ]
 
+[[package]]
+name = "juno_product_read"
+version = "0.1.0"
+dependencies = [
+ "async-std",
+ "hercules_rt",
+ "juno_build",
+ "with_builtin_macros",
+]
+
 [[package]]
 name = "juno_schedule_test"
 version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
index eeb5e69d92410b2174c1db19886b0ff76f773257..3e86bad053f8847c9f10d18117635de1cfa76250 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,4 +33,5 @@ members = [
 	"juno_samples/edge_detection",
 	"juno_samples/fork_join_tests",
 	"juno_samples/multi_device",
+	"juno_samples/product_read",
 ]
diff --git a/juno_samples/product_read/Cargo.toml b/juno_samples/product_read/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..d466f5550b77e426040842339684a1e8906b22fa
--- /dev/null
+++ b/juno_samples/product_read/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "juno_product_read"
+version = "0.1.0"
+authors = ["Aaron Councilman <aaronjc4@illinois.edu>"]
+edition = "2021"
+
+[[bin]]
+name = "juno_product_read"
+path = "src/main.rs"
+
+[features]
+cuda = ["juno_build/cuda", "hercules_rt/cuda"]
+
+[build-dependencies]
+juno_build = { path = "../../juno_build" }
+
+[dependencies]
+juno_build = { path = "../../juno_build" }
+hercules_rt = { path = "../../hercules_rt" }
+with_builtin_macros = "0.1.0"
+async-std = "*"
diff --git a/juno_samples/product_read/build.rs b/juno_samples/product_read/build.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2bd5172e661e65e2284a986e2d710cd890d71b90
--- /dev/null
+++ b/juno_samples/product_read/build.rs
@@ -0,0 +1,22 @@
+use juno_build::JunoCompiler;
+
+fn main() {
+    #[cfg(not(feature = "cuda"))]
+    {
+        JunoCompiler::new()
+            .file_in_src("product_read.jn")
+            .unwrap()
+            .build()
+            .unwrap();
+    }
+    #[cfg(feature = "cuda")]
+    {
+        JunoCompiler::new()
+            .file_in_src("product_read.jn")
+            .unwrap()
+            .schedule_in_src("gpu.sch")
+            .unwrap()
+            .build()
+            .unwrap();
+    }
+}
diff --git a/juno_samples/product_read/src/gpu.sch b/juno_samples/product_read/src/gpu.sch
new file mode 100644
index 0000000000000000000000000000000000000000..549b421561da50023719fd432fe8d943a4ab37f6
--- /dev/null
+++ b/juno_samples/product_read/src/gpu.sch
@@ -0,0 +1,19 @@
+gvn(*);
+phi-elim(*);
+dce(*);
+
+let out = auto-outline(*);
+gpu(out.product_read);
+
+ip-sroa(*);
+sroa(*);
+crc(*);
+dce(*);
+gvn(*);
+phi-elim(*);
+dce(*);
+
+infer-schedules(*);
+
+float-collections(*);
+gcm(*);
diff --git a/juno_samples/product_read/src/main.rs b/juno_samples/product_read/src/main.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5211098ceebd6d7b15871ba0dd73cdbefb993313
--- /dev/null
+++ b/juno_samples/product_read/src/main.rs
@@ -0,0 +1,20 @@
+#![feature(concat_idents)]
+
+use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox};
+
+juno_build::juno!("product_read");
+
+fn main() {
+    async_std::task::block_on(async {
+        let input = vec![(0, 1), (2, 3)];
+        let input : HerculesImmBox<(i32, i32)> = HerculesImmBox::from(input.as_slice());
+        let mut r = runner!(product_read);
+        let res : Vec<i32> = HerculesMutBox::from(r.run(input.to()).await).as_slice().to_vec();
+        assert_eq!(res, vec![0, 1, 2, 3]);
+    });
+}
+
+#[test]
+fn products_test() {
+    main();
+}
diff --git a/juno_samples/product_read/src/product_read.jn b/juno_samples/product_read/src/product_read.jn
new file mode 100644
index 0000000000000000000000000000000000000000..7bf74a105b32099341f299c38898f6f6c08eb467
--- /dev/null
+++ b/juno_samples/product_read/src/product_read.jn
@@ -0,0 +1,9 @@
+#[entry]
+fn product_read(input: (i32, i32)[2]) -> i32[4] {
+  let result : i32[4];
+  result[0] = input[0].0;
+  result[1] = input[0].1;
+  result[2] = input[1].0;
+  result[3] = input[1].1;
+  return result;
+}