diff --git a/Cargo.lock b/Cargo.lock index 73ab201c405dd39e11fb32dc014cde9a8e44fc12..13cadc9592c8e1d95e21c013f465919ffcf6c5ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -697,6 +697,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "juno_antideps" +version = "0.1.0" +dependencies = [ + "async-std", + "juno_build", + "with_builtin_macros", +] + [[package]] name = "juno_build" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index badc4260d3f2e1dae31d0d8e294c97aeee4b4fc8..1db806f41befe6b20d89b8484e069a4674276d6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,5 +24,6 @@ members = [ "juno_samples/matmul", "juno_samples/casts_and_intrinsics", "juno_samples/nested_ccp", + "juno_samples/antideps", #"juno_samples/implicit_clone", ] diff --git a/hercules_cg/src/cpu.rs b/hercules_cg/src/cpu.rs index fb7f653b9eb9dc9d39846210a4de5547b398c991..a09eacfa621876a570d37bd96e1d1f534e94fa4e 100644 --- a/hercules_cg/src/cpu.rs +++ b/hercules_cg/src/cpu.rs @@ -1,13 +1,10 @@ -extern crate bitvec; extern crate hercules_ir; -use std::collections::{BTreeMap, VecDeque}; +use std::collections::BTreeMap; use std::fmt::{Error, Write}; -use std::iter::{zip, FromIterator}; +use std::iter::zip; use std::sync::atomic::{AtomicUsize, Ordering}; -use self::bitvec::prelude::*; - use self::hercules_ir::*; use crate::*; @@ -28,7 +25,7 @@ pub fn cpu_codegen<W: Write>( typing: &Vec<TypeID>, control_subgraph: &Subgraph, antideps: &Vec<(NodeID, NodeID)>, - bbs: &Vec<NodeID>, + bbs: &BasicBlocks, w: &mut W, ) -> Result<(), Error> { let ctx = CPUContext { @@ -54,7 +51,7 @@ struct CPUContext<'a> { typing: &'a Vec<TypeID>, control_subgraph: &'a Subgraph, antideps: &'a Vec<(NodeID, NodeID)>, - bbs: &'a Vec<NodeID>, + bbs: &'a BasicBlocks, } #[derive(Default, Debug)] @@ -125,31 +122,9 @@ impl<'a> CPUContext<'a> { )?; // Emit data flow into basic blocks. - let mut worklist = VecDeque::from_iter( - self.reverse_postorder - .into_iter() - .filter(|id| !self.function.nodes[id.idx()].is_control()), - ); - let mut visited = bitvec![u8, Lsb0; 0; self.function.nodes.len()]; - let antideps = flip_antideps(&self.antideps); - while let Some(id) = worklist.pop_front() { - let node = &self.function.nodes[id.idx()]; - if node.is_phi() - || node.is_reduce() - || get_uses(node) - .as_ref() - .into_iter() - .chain(antideps.get(&id).into_iter().flatten()) - .all(|u| { - self.function.nodes[u.idx()].is_control() - || self.bbs[u.idx()] != self.bbs[id.idx()] - || visited[u.idx()] - }) - { + for block in self.bbs.1.iter() { + for id in block { self.codegen_data_node(*id, &mut blocks)?; - visited.set(id.idx(), true); - } else { - worklist.push_back(id); } } @@ -240,7 +215,7 @@ impl<'a> CPUContext<'a> { ) -> Result<(), Error> { match self.function.nodes[id.idx()] { Node::Phi { control, ref data } => { - let phis = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().phis; + let phis = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().phis; let preds = self.function.nodes[control.idx()].try_region().unwrap(); write!( phis, @@ -262,7 +237,7 @@ impl<'a> CPUContext<'a> { write!(phis, "\n")?; } Node::Parameter { index } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; let ty = self.get_type(self.typing[id.idx()]); write!( body, @@ -274,7 +249,7 @@ impl<'a> CPUContext<'a> { )?; } Node::Constant { id: cons_id } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; write!(body, " {} = bitcast ", self.get_value(id, false))?; match self.constants[cons_id.idx()] { Constant::Boolean(val) => write!(body, "i1 {} to i1\n", val)?, @@ -304,7 +279,7 @@ impl<'a> CPUContext<'a> { } } Node::DynamicConstant { id: dc_id } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; // Dynamic constants are all pre-calculated at the top of the // function. write!( @@ -315,7 +290,7 @@ impl<'a> CPUContext<'a> { )? } Node::Unary { op, input } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; match op { UnaryOperator::Not => write!( body, @@ -450,7 +425,7 @@ impl<'a> CPUContext<'a> { (BinaryOperator::RSh, _) => "ashr", }; - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; write!( body, " {} = {} {}, {}\n", @@ -466,7 +441,7 @@ impl<'a> CPUContext<'a> { second, third, } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; match op { TernaryOperator::Select => write!( body, @@ -482,7 +457,7 @@ impl<'a> CPUContext<'a> { intrinsic, ref args, } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; write!( body, " {} = call {} {}(", @@ -502,7 +477,7 @@ impl<'a> CPUContext<'a> { collect, ref indices, } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; let collect_name = self.get_value(collect, false); let collect_ty = self.typing[collect.idx()]; let index_ptr_name = @@ -534,7 +509,7 @@ impl<'a> CPUContext<'a> { data, ref indices, } => { - let body = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap().body; + let body = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap().body; let collect_name = self.get_value(collect, false); let collect_ty = self.typing[collect.idx()]; let index_ptr_name = diff --git a/hercules_cg/src/rt.rs b/hercules_cg/src/rt.rs index 44aad61d72cdc2add0d46522da5d65f32dd58348..890c898d75841c85756f3b6e2dd0011678e7789b 100644 --- a/hercules_cg/src/rt.rs +++ b/hercules_cg/src/rt.rs @@ -1,11 +1,8 @@ -extern crate bitvec; extern crate hercules_ir; -use std::collections::{BTreeMap, VecDeque}; +use std::collections::BTreeMap; use std::fmt::{Error, Write}; -use std::iter::{zip, FromIterator}; - -use self::bitvec::prelude::*; +use std::iter::zip; use self::hercules_ir::*; @@ -23,7 +20,7 @@ pub fn rt_codegen<W: Write>( typing: &Vec<TypeID>, control_subgraph: &Subgraph, antideps: &Vec<(NodeID, NodeID)>, - bbs: &Vec<NodeID>, + bbs: &BasicBlocks, collection_objects: &CollectionObjects, callgraph: &CallGraph, devices: &Vec<Device>, @@ -51,7 +48,7 @@ struct RTContext<'a> { typing: &'a Vec<TypeID>, control_subgraph: &'a Subgraph, antideps: &'a Vec<(NodeID, NodeID)>, - bbs: &'a Vec<NodeID>, + bbs: &'a BasicBlocks, collection_objects: &'a CollectionObjects, callgraph: &'a CallGraph, devices: &'a Vec<Device>, @@ -215,31 +212,9 @@ impl<'a> RTContext<'a> { .collect(); // Emit data flow into basic blocks. - let mut worklist = VecDeque::from_iter( - self.reverse_postorder - .into_iter() - .filter(|id| !func.nodes[id.idx()].is_control()), - ); - let mut visited = bitvec![u8, Lsb0; 0; func.nodes.len()]; - let antideps = flip_antideps(&self.antideps); - while let Some(id) = worklist.pop_front() { - let node = &func.nodes[id.idx()]; - if node.is_phi() - || node.is_reduce() - || get_uses(node) - .as_ref() - .into_iter() - .chain(antideps.get(&id).into_iter().flatten()) - .all(|u| { - func.nodes[u.idx()].is_control() - || self.bbs[u.idx()] != self.bbs[id.idx()] - || visited[u.idx()] - }) - { + for block in self.bbs.1.iter() { + for id in block { self.codegen_data_node(*id, &mut blocks)?; - visited.set(id.idx(), true); - } else { - worklist.push_back(id); } } @@ -340,7 +315,7 @@ impl<'a> RTContext<'a> { let func = &self.get_func(); match func.nodes[id.idx()] { Node::Parameter { index } => { - let block = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap(); + let block = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap(); write!( block, " {} = p{};\n", @@ -349,7 +324,7 @@ impl<'a> RTContext<'a> { )? } Node::Constant { id: cons_id } => { - let block = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap(); + let block = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap(); write!(block, " {} = ", self.get_value(id))?; match self.module.constants[cons_id.idx()] { Constant::Boolean(val) => write!(block, "{}bool", val)?, @@ -384,7 +359,7 @@ impl<'a> RTContext<'a> { } => { match self.devices[callee_id.idx()] { Device::LLVM => { - let block = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap(); + let block = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap(); write!( block, " {} = unsafe {{ {}(", @@ -465,7 +440,7 @@ impl<'a> RTContext<'a> { } } Device::AsyncRust => { - let block = &mut blocks.get_mut(&self.bbs[id.idx()]).unwrap(); + let block = &mut blocks.get_mut(&self.bbs.0[id.idx()]).unwrap(); write!( block, " {} = {}(", diff --git a/hercules_ir/src/antideps.rs b/hercules_ir/src/antideps.rs index 73ea30302d7022de7c03c0d1b3581e029cdc9ace..8aa9f7d9d38051e6516a96b07105edd17a7864d6 100644 --- a/hercules_ir/src/antideps.rs +++ b/hercules_ir/src/antideps.rs @@ -135,7 +135,7 @@ pub fn antideps( }); // Second, we generate anti-dependence edges from the dataflow analysis. - // There are three cases where an anti-dependence edge is generated: + // There are four cases where an anti-dependence edge is generated: // // 1. A read node and a write node share an object and generation pair on // their `collect` input. @@ -145,6 +145,9 @@ pub fn antideps( // 3. A call node and a write node share an object and generation pair, // where the pair is on any input of the call node and the pair is on the // write's `collect` input. + // 4. A call node and another call node share an object and generation pair, + // where the pair is on any input of both call nodes AND the second call + // node is a mutator of the object. let mut reads_writes_calls_mut_calls_per_pair: BTreeMap< (CollectionObjectID, NodeID), (Vec<NodeID>, Vec<NodeID>, Vec<NodeID>, Vec<NodeID>), @@ -205,28 +208,47 @@ pub fn antideps( } } - // Once we've matched reads / writes / calls by object and generation pair, - // the pair itself no longer matters. + // Once we've grouped reads / writes / calls by pairs, we create pair-wise + // anti-dependence edges. Due to loops, a write may technically anti-depend + // on a read where the read depends on the write, but we don't want to + // generate that anti-dependence edge, since it'll create a cycle during + // backend code generation. Thus, if the mutator in an anti-dependence is + // the same as the generation of the current pair, don't generate the edge. let mut antideps = vec![]; - for (_, (reads, writes, calls, mut_calls)) in reads_writes_calls_mut_calls_per_pair { + for ((_, gen), (reads, writes, calls, mut_calls)) in reads_writes_calls_mut_calls_per_pair { // Case 1: for read in reads.iter() { for write in writes.iter() { - antideps.push((*read, *write)); + if *write != gen { + antideps.push((*read, *write)); + } } } // Case 2: for read in reads.iter() { for mut_call in mut_calls.iter() { - antideps.push((*read, *mut_call)); + if *mut_call != gen { + antideps.push((*read, *mut_call)); + } } } // Case 3: for call in calls.iter().chain(mut_calls.iter()) { for write in writes.iter() { - antideps.push((*call, *write)); + if *write != gen { + antideps.push((*call, *write)); + } + } + } + + // Case 4: + for call in calls.iter().chain(mut_calls.iter()) { + for mut_call in mut_calls.iter() { + if *mut_call != gen && *call != *mut_call { + antideps.push((*call, *mut_call)); + } } } } @@ -247,3 +269,17 @@ pub fn flip_antideps(antideps: &Vec<(NodeID, NodeID)>) -> BTreeMap<NodeID, Vec<N result } + +/* + * Utility to make a map from node to anti-dependency users (map reads -> + * mutators). + */ +pub fn map_antideps(antideps: &Vec<(NodeID, NodeID)>) -> BTreeMap<NodeID, Vec<NodeID>> { + let mut result: BTreeMap<NodeID, Vec<NodeID>> = BTreeMap::new(); + + for (read, mutator) in antideps { + result.entry(*read).or_default().push(*mutator); + } + + result +} diff --git a/hercules_ir/src/dot.rs b/hercules_ir/src/dot.rs index a8754e78218d1b63a18bc8abd4df074fca193505..5ef16bb1c61846a36b78e308767838c03fb8ede0 100644 --- a/hercules_ir/src/dot.rs +++ b/hercules_ir/src/dot.rs @@ -20,7 +20,7 @@ pub fn xdot_module( reverse_postorders: &Vec<Vec<NodeID>>, doms: Option<&Vec<DomTree>>, fork_join_maps: Option<&Vec<HashMap<NodeID, NodeID>>>, - bbs: Option<&Vec<Vec<NodeID>>>, + bbs: Option<&Vec<BasicBlocks>>, ) { let mut tmp_path = temp_dir(); let mut rng = rand::thread_rng(); @@ -55,7 +55,7 @@ pub fn write_dot<W: Write>( reverse_postorders: &Vec<Vec<NodeID>>, doms: Option<&Vec<DomTree>>, fork_join_maps: Option<&Vec<HashMap<NodeID, NodeID>>>, - bbs: Option<&Vec<Vec<NodeID>>>, + bbs: Option<&Vec<BasicBlocks>>, w: &mut W, ) -> std::fmt::Result { write_digraph_header(w)?; @@ -173,9 +173,9 @@ pub fn write_dot<W: Write>( // Step 4: draw BB edges in olive. if let Some(bbs) = bbs { let bbs = &bbs[function_id.idx()]; - for node_idx in 0..bbs.len() { + for node_idx in 0..bbs.0.len() { let maybe_data = NodeID::new(node_idx); - let control = bbs[node_idx]; + let control = bbs.0[node_idx]; if maybe_data != control { write_edge( maybe_data, diff --git a/hercules_ir/src/gcm.rs b/hercules_ir/src/gcm.rs index 35541d18534337888ee94a80134e9f3aa3b3b430..a8fd0a21d83ec1b827954a848481953b0d39ba25 100644 --- a/hercules_ir/src/gcm.rs +++ b/hercules_ir/src/gcm.rs @@ -7,6 +7,18 @@ use self::bitvec::prelude::*; use crate::*; +/* + * Basic block info consists of two things: + * + * 1. A map from node to block (named by control nodes). + * 2. For each node, which nodes are in its own block. + * + * Note that for #2, the structure is Vec<NodeID>, meaning the nodes are ordered + * inside the block. This order corresponds to the traversal order of the nodes + * in the block needed by the backend code generators. + */ +pub type BasicBlocks = (Vec<NodeID>, Vec<Vec<NodeID>>); + /* * Top level global code motion function. Assigns each data node to one of its * immediate control use / user nodes, forming (unordered) basic blocks. Returns @@ -22,7 +34,7 @@ pub fn gcm( antideps: &Vec<(NodeID, NodeID)>, loops: &LoopTree, fork_join_map: &HashMap<NodeID, NodeID>, -) -> Vec<NodeID> { +) -> BasicBlocks { let mut bbs: Vec<Option<NodeID>> = vec![None; function.nodes.len()]; // Step 1: assign the basic block locations of all nodes that must be in a @@ -57,10 +69,6 @@ pub fn gcm( // Step 2: schedule early. Place nodes in the earliest position they could // go - use worklist to iterate nodes. let mut schedule_early = bbs.clone(); - let mut antideps_uses = HashMap::<NodeID, Vec<NodeID>>::new(); - for (read, write) in antideps { - antideps_uses.entry(*write).or_default().push(*read); - } let mut worklist = VecDeque::from(reverse_postorder.clone()); while let Some(id) = worklist.pop_front() { if schedule_early[id.idx()].is_some() { @@ -73,15 +81,6 @@ pub fn gcm( .as_ref() .into_iter() .map(|id| *id) - // TODO: once anti-dependence analysis is fixed, use it in GCM. - // Include "uses" from anti-dependencies. - //.chain( - // antideps_uses - // .get(&id) - // .unwrap_or(&vec![]) - // .into_iter() - // .map(|id| *id), - //) .map(|id| schedule_early[id.idx()]) .collect(); if let Some(use_places) = use_places { @@ -103,10 +102,6 @@ pub fn gcm( .into_iter() .map(|(fork, join)| (*join, *fork)) .collect(); - let mut antideps_users = HashMap::<NodeID, Vec<NodeID>>::new(); - for (read, write) in antideps { - antideps_users.entry(*read).or_default().push(*write); - } let mut worklist = VecDeque::from_iter(reverse_postorder.into_iter().map(|id| *id).rev()); while let Some(id) = worklist.pop_front() { if bbs[id.idx()].is_some() { @@ -128,17 +123,7 @@ pub fn gcm( // For every user, consider where we need to be to directly dominate the // user. - for user in def_use.get_users(id).as_ref().into_iter().map(|id| *id) - // TODO: once anti-dependence analysis is fixed, use it in GCM. - // Include "users" from anti-dependencies. - //.chain( - // antideps_users - // .get(&id) - // .unwrap_or(&vec![]) - // .into_iter() - // .map(|id| *id), - //) - { + for user in def_use.get_users(id).as_ref().into_iter().map(|id| *id) { if let Node::Phi { control, data } = &function.nodes[user.idx()] { // For phis, we need to dominate the block jumping to the phi in // the slot that corresponds to our use. @@ -215,8 +200,40 @@ pub fn gcm( bbs[id.idx()] = Some(location); } + let bbs: Vec<_> = bbs.into_iter().map(Option::unwrap).collect(); + + // Step 4: determine the order of nodes inside each block. Use worklist to + // add nodes to blocks in order that obeys dependencies. + let mut order: Vec<Vec<NodeID>> = vec![vec![]; function.nodes.len()]; + let mut worklist = VecDeque::from_iter( + reverse_postorder + .into_iter() + .filter(|id| !function.nodes[id.idx()].is_control()), + ); + let mut visited = bitvec![u8, Lsb0; 0; function.nodes.len()]; + let antideps = flip_antideps(&antideps); + while let Some(id) = worklist.pop_front() { + let node = &function.nodes[id.idx()]; + if node.is_phi() + || node.is_reduce() + || get_uses(node) + .as_ref() + .into_iter() + .chain(antideps.get(&id).into_iter().flatten()) + .all(|u| { + function.nodes[u.idx()].is_control() + || bbs[u.idx()] != bbs[id.idx()] + || visited[u.idx()] + }) + { + order[bbs[id.idx()].idx()].push(*id); + visited.set(id.idx(), true); + } else { + worklist.push_back(id); + } + } - bbs.into_iter().map(Option::unwrap).collect() + (bbs, order) } /* diff --git a/hercules_opt/src/pass.rs b/hercules_opt/src/pass.rs index 796f8c7945be4bc66e51a9956c26ebe79f486496..c02e967e355f67da934d9e49ffccff8c04e1fc11 100644 --- a/hercules_opt/src/pass.rs +++ b/hercules_opt/src/pass.rs @@ -74,7 +74,7 @@ pub struct PassManager { pub reduce_cycles: Option<Vec<HashMap<NodeID, HashSet<NodeID>>>>, pub antideps: Option<Vec<Vec<(NodeID, NodeID)>>>, pub data_nodes_in_fork_joins: Option<Vec<HashMap<NodeID, HashSet<NodeID>>>>, - pub bbs: Option<Vec<Vec<NodeID>>>, + pub bbs: Option<Vec<BasicBlocks>>, pub collection_objects: Option<CollectionObjects>, pub callgraph: Option<CallGraph>, } diff --git a/juno_samples/antideps/Cargo.toml b/juno_samples/antideps/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..40b4d47c57bbe422bfe983ee73a1d140a2ab1b94 --- /dev/null +++ b/juno_samples/antideps/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "juno_antideps" +version = "0.1.0" +authors = ["Russel Arbore <rarbore2@illinois.edu>"] +edition = "2021" + +[[bin]] +name = "juno_antideps" +path = "src/main.rs" + +[build-dependencies] +juno_build = { path = "../../juno_build" } + +[dependencies] +juno_build = { path = "../../juno_build" } +with_builtin_macros = "0.1.0" +async-std = "*" diff --git a/juno_samples/antideps/build.rs b/juno_samples/antideps/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..757243b829c3f805f8d87d38676e72e2b532f072 --- /dev/null +++ b/juno_samples/antideps/build.rs @@ -0,0 +1,10 @@ +extern crate juno_build; +use juno_build::JunoCompiler; + +fn main() { + JunoCompiler::new() + .file_in_src("antideps.jn") + .unwrap() + .build() + .unwrap(); +} diff --git a/juno_samples/antideps/src/antideps.jn b/juno_samples/antideps/src/antideps.jn new file mode 100644 index 0000000000000000000000000000000000000000..f54b8dcf4050f95a749daf336931f746a5a942d1 --- /dev/null +++ b/juno_samples/antideps/src/antideps.jn @@ -0,0 +1,24 @@ +#[entry] +fn simple_antideps(a : usize, b : usize) -> i32 { + let arr : i32[3]; + let r = arr[b]; + arr[a] = 5; + return r + arr[b]; +} + +#[entry] +fn complex_antideps(x : i32) -> i32 { + let arr : i32[4]; + arr[1] = 7; + let r = 0; + while x > 6 { + if x > 5 { + r = arr[1]; + } else { + arr[1] = 8; + r = arr[1]; + } + x -= 1; + } + return r; +} diff --git a/juno_samples/antideps/src/main.rs b/juno_samples/antideps/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..e613f5ffbec5de4499b7e66279a1feca16883c0e --- /dev/null +++ b/juno_samples/antideps/src/main.rs @@ -0,0 +1,23 @@ +#![feature(future_join, box_as_ptr)] + +extern crate async_std; +extern crate juno_build; + +juno_build::juno!("antideps"); + +fn main() { + async_std::task::block_on(async { + let output = simple_antideps(1, 1).await; + println!("{}", output); + assert_eq!(output, 5); + + let output = complex_antideps(9).await; + println!("{}", output); + assert_eq!(output, 7); + }); +} + +#[test] +fn antideps_test() { + main(); +} diff --git a/juno_samples/implicit_clone/src/implicit_clone.jn b/juno_samples/implicit_clone/src/implicit_clone.jn index 6dfaff6c69cd7d553ba8075b9507d526c3268f82..17e345e51e80db27c0d2f21854e22abf1eefcdb8 100644 --- a/juno_samples/implicit_clone/src/implicit_clone.jn +++ b/juno_samples/implicit_clone/src/implicit_clone.jn @@ -1,11 +1,3 @@ -#[entry] -fn antideps(a : usize, b : usize) -> i32 { - let arr : i32[3]; - let r = arr[b]; - arr[a] = 5; - return r + arr[b]; -} - #[entry] fn implicit_clone(input : i32) -> i32 { let arr : i32[3]; diff --git a/juno_samples/implicit_clone/src/main.rs b/juno_samples/implicit_clone/src/main.rs index 73edc4646972bd100c10edbc7c87c930c8003b70..5ff952a36a8052cda2a0031b2551cd6452a727f3 100644 --- a/juno_samples/implicit_clone/src/main.rs +++ b/juno_samples/implicit_clone/src/main.rs @@ -7,10 +7,6 @@ juno_build::juno!("implicit_clone"); fn main() { async_std::task::block_on(async { - let output = antideps(1, 1).await; - println!("{}", output); - assert_eq!(output, 5); - let output = implicit_clone(3).await; println!("{}", output); assert_eq!(output, 9);