From 3c9937d570c7479992c6e2c8f802d88f27187de4 Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Thu, 26 Sep 2024 08:03:35 -0400 Subject: [PATCH] [compiler-v2] Variable window peephole optimization --- .../aptos_test_harness/diamond_clicker.v2_exp | 18 +- .../tests/aptos_test_harness/table.v2_exp | 2 +- .../peephole_optimizer.rs | 10 +- .../peephole_optimizer/inefficient_binops.rs | 51 ----- .../peephole_optimizer/inefficient_loads.rs | 77 ++++++++ .../peephole_optimizer/optimizers.rs | 42 ++-- .../peephole_optimizer/reducible_pairs.rs | 36 ++-- .../file-format-generator/fields.opt.exp | 18 +- .../file-format-generator/globals.opt.exp | 16 +- .../file-format-generator/multi_use.opt.exp | 14 +- .../file-format-generator/opt_load_01.exp | 109 +++++++++++ .../file-format-generator/opt_load_01.move | 16 ++ .../file-format-generator/opt_load_01.opt.exp | 66 +++++++ .../file-format-generator/opt_load_02.exp | 180 ++++++++++++++++++ .../file-format-generator/opt_load_02.move | 29 +++ .../file-format-generator/opt_load_02.opt.exp | 129 +++++++++++++ .../file-format-generator/opt_load_04.exp | 34 ++++ .../file-format-generator/opt_load_04.move | 10 + .../file-format-generator/opt_load_04.opt.exp | 30 +++ .../file-format-generator/opt_load_05.exp | 56 ++++++ .../file-format-generator/opt_load_05.move | 22 +++ .../file-format-generator/opt_load_05.opt.exp | 48 +++++ .../tests/flush-writes/loop_01.off.exp | 12 +- .../unused_flush_early_02.off.exp | 24 ++- .../unused_flush_early_03.off.exp | 36 ++-- .../tests/flush-writes/write_ref_01.off.exp | 12 +- .../variable-coalescing/intermingled_2.exp | 16 +- .../variable-coalescing/intermingled_3.exp | 14 +- .../variable-coalescing/overlapping_vars.exp | 8 +- .../variable-coalescing/reassigned_var.exp | 10 +- ...different_offsets.optimize-no-simplify.exp | 2 +- .../pack.v2_exp | 36 ++++ .../sources/functional/enum_abort.v2_exp | 3 +- .../functional/generic_invariants.v2_exp | 16 -- .../move/scripts/compare_num_instructions.py | 14 +- 35 files changed, 980 insertions(+), 236 deletions(-) delete mode 100644 third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_binops.rs create mode 100644 third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_loads.rs create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.move create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.move create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.move create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.move create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp create mode 100644 third_party/move/move-prover/bytecode-pipeline/tests/data_invariant_instrumentation/pack.v2_exp diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp index e454cf5a17b59..53f845c17f340 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp @@ -33,26 +33,26 @@ B0: 9: MutBorrowField[0](OuterStruct.any_field: vector) 10: StLoc[2](loc1: &mut vector) 11: LdU64(0) - 12: CopyLoc[2](loc1: &mut vector) - 13: FreezeRef - 14: VecLen(3) - 15: StLoc[3](loc2: u64) + 12: StLoc[3](loc2: u64) + 13: CopyLoc[2](loc1: &mut vector) + 14: FreezeRef + 15: VecLen(3) 16: StLoc[4](loc3: u64) B1: - 17: CopyLoc[4](loc3: u64) - 18: CopyLoc[3](loc2: u64) + 17: CopyLoc[3](loc2: u64) + 18: CopyLoc[4](loc3: u64) 19: Lt 20: BrFalse(31) B2: 21: CopyLoc[2](loc1: &mut vector) - 22: CopyLoc[4](loc3: u64) + 22: CopyLoc[3](loc2: u64) 23: VecMutBorrow(3) 24: FreezeRef 25: Call debug::print(&InnerStruct) - 26: MoveLoc[4](loc3: u64) + 26: MoveLoc[3](loc2: u64) 27: LdU64(1) 28: Add - 29: StLoc[4](loc3: u64) + 29: StLoc[3](loc2: u64) 30: Branch(34) B3: 31: MoveLoc[2](loc1: &mut vector) diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/table.v2_exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/table.v2_exp index b0352e4c59288..d313008fc3358 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/table.v2_exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/table.v2_exp @@ -52,7 +52,7 @@ Events: } { type: 0x1::transaction_fee::FeeStatement - data: "9c0000000000000007000000000000000400000000000000c83a0200000000000000000000000000" + data: "9c0000000000000006000000000000000400000000000000c83a0200000000000000000000000000" }mutable inputs after call: local#0: 0 return values: 0 diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer.rs b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer.rs index 1450ce9f707fd..70919d6dafa7a 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer.rs @@ -5,16 +5,16 @@ //! Peephole optimizations assume that the bytecode is valid, and all user-facing //! error checks have already been performed. -pub mod inefficient_binops; +pub mod inefficient_loads; pub mod optimizers; pub mod reducible_pairs; -use inefficient_binops::TransformInefficientBinops; +use inefficient_loads::InefficientLoads; use move_binary_format::{ control_flow_graph::{ControlFlowGraph, VMControlFlowGraph}, file_format::{Bytecode, CodeOffset, CodeUnit}, }; -use optimizers::{BasicBlockOptimizer, FixedWindowProcessor}; +use optimizers::{BasicBlockOptimizer, WindowProcessor}; use reducible_pairs::ReduciblePairs; use std::{collections::BTreeMap, mem}; @@ -36,8 +36,8 @@ impl BasicBlockOptimizerPipeline { pub fn default() -> Self { Self { optimizers: vec![ - Box::new(FixedWindowProcessor::new(ReduciblePairs)), - Box::new(FixedWindowProcessor::new(TransformInefficientBinops)), + Box::new(WindowProcessor::new(ReduciblePairs)), + Box::new(WindowProcessor::new(InefficientLoads)), ], } } diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_binops.rs b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_binops.rs deleted file mode 100644 index 83ac33aa387f5..0000000000000 --- a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_binops.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -//! This module contains a fixed window peephole optimizer for the Move bytecode. -//! As with all peephole optimizers here, it assumes that the bytecode is valid. -//! -//! We consider fixed windows of size 5 for this optimizer. -//! -//! This optimizer addresses a commonly appearing pattern when compiling binary -//! operations where the second operand to the operation is a constant. -//! -//! The pattern is: -//! 1. Load the constant (second operand) on the stack. -//! 2. Store the constant in a local `u`. -//! 3. Copy or Move some value on the stack (first operand) from local `v`. -//! 4. Move the constant from `u` back to the stack (second operand). -//! -//! We replace it with: -//! 1. Copy or Move the first operand to the stack. -//! 2. Load the constant (second operand) on the stack. -//! -//! This transformation leaves the stack in the same state. -//! The local `u` in the original code has been moved from, so later code -//! cannot use it without a subsequent store. -//! So, not writing back to `u` is safe, as long as `u` != `v`. - -use crate::file_format_generator::peephole_optimizer::optimizers::FixedWindowOptimizer; -use move_binary_format::file_format::Bytecode; - -pub struct TransformInefficientBinops; - -impl FixedWindowOptimizer for TransformInefficientBinops { - fn fixed_window_size(&self) -> usize { - 4 - } - - fn optimize_fixed_window(&self, window: &[Bytecode]) -> Option> { - use Bytecode::*; - // See module documentation for more behind the rationale. - match (&window[0], &window[1], &window[2], &window[3]) { - ( - LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) | LdU128(_) | LdU256(_) | LdConst(_) - | LdTrue | LdFalse, - StLoc(u), - CopyLoc(v) | MoveLoc(v), - MoveLoc(w), - ) if *u == *w && *u != *v => Some(vec![window[2].clone(), window[0].clone()]), - _ => None, - } - } -} diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_loads.rs b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_loads.rs new file mode 100644 index 0000000000000..6aa84b2812c29 --- /dev/null +++ b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/inefficient_loads.rs @@ -0,0 +1,77 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! This module contains a window peephole optimizer for the Move bytecode. +//! As with all peephole optimizers here, it assumes that the bytecode is valid. +//! +//! This optimizer addresses a commonly appearing pattern when involving loads. +//! +//! The pattern is: +//! 1. Load a constant into the stack. +//! 2. Store the constant into a local `u`. +//! 3. A (possibly empty) sequence of instructions that do not involve `u`, +//! which we name `sequence`. Currently, the only instructions that can +//! involve `u` are: `CopyLoc`, `MoveLoc`, `StLoc`, `ImmBorrowLoc`, +//! and `MutBorrowLoc`. +//! 4. A `MoveLoc` of `u`. +//! +//! This pattern can be replaced with: +//! 1. `sequence`. +//! 2. Load the constant into the stack. +//! +//! This transformation leaves the stack in the same state. +//! The local `u` in the original code has been moved from, so later code +//! cannot use it without a subsequent store. +//! So, skipping the store to `u` is safe. + +use crate::file_format_generator::peephole_optimizer::optimizers::WindowOptimizer; +use move_binary_format::file_format::Bytecode; + +/// An optimizer for inefficient loads. +pub struct InefficientLoads; + +impl InefficientLoads { + // We need at least 3 instructions, corresponding to points 1, 2, and 4 in the pattern + // described in the module documentation (at the top of the file). + const MIN_WINDOW_SIZE: usize = 3; +} + +impl WindowOptimizer for InefficientLoads { + fn optimize_window(&self, window: &[Bytecode]) -> Option<(Vec, usize)> { + use Bytecode::*; + if window.len() < Self::MIN_WINDOW_SIZE { + return None; + } + // Load and Store a constant into `u`. + let u = match (&window[0], &window[1]) { + ( + LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) | LdU128(_) | LdU256(_) | LdConst(_) + | LdTrue | LdFalse, + StLoc(u), + ) => *u, + _ => return None, + }; + for (index, instr) in window[2..].iter().enumerate() { + match instr { + CopyLoc(v) | StLoc(v) | ImmBorrowLoc(v) | MutBorrowLoc(v) if u == *v => { + // We have encountered an instruction that involves `u`. + return None; + }, + MoveLoc(v) if u == *v => { + // We have reached the end of the pattern (point 4 in the module documentation). + let sequence = &window[2..index + 2]; + let load_constant = &window[0..1]; + return Some(( + [sequence, load_constant].concat(), + index + Self::MIN_WINDOW_SIZE, + )); + }, + _ => { + // Instruction that does not involve `u`, including `MoveLoc` of a different local. + }, + } + } + // The full pattern was not found. + None + } +} diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/optimizers.rs b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/optimizers.rs index 7a6fb10817079..0bcabb5675092 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/optimizers.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/optimizers.rs @@ -11,22 +11,20 @@ pub trait BasicBlockOptimizer { fn optimize(&self, block: &[Bytecode]) -> Vec; } -/// An optimizer for a fixed window of bytecode. -/// The fixed window can be assumed to be within a basic block. -pub trait FixedWindowOptimizer { - /// The fixed window size for this optimizer. - fn fixed_window_size(&self) -> usize; - - /// Given a fixed `window` of bytecode of size `self.fixed_window_size()`, - /// optionally return its optimized version. +/// An optimizer for a window of bytecode within a basic block. +/// The window is always a suffix of a basic block. +pub trait WindowOptimizer { + /// Given a `window` of bytecode, return a tuple containing: + /// 1. an optimized version of a non-empty prefix of the `window`. + /// 2. size of this prefix (should be non-zero). /// If `None` is returned, the `window` is not optimized. - fn optimize_fixed_window(&self, window: &[Bytecode]) -> Option>; + fn optimize_window(&self, window: &[Bytecode]) -> Option<(Vec, usize)>; } -/// A processor to perform fixed window optimizations of a particular style on a basic block. -pub struct FixedWindowProcessor(T); +/// A processor to perform window optimizations of a particular style on a basic block. +pub struct WindowProcessor(T); -impl BasicBlockOptimizer for FixedWindowProcessor { +impl BasicBlockOptimizer for WindowProcessor { fn optimize(&self, block: &[Bytecode]) -> Vec { let mut old_block = block.to_vec(); // Run single passes until code stops changing. @@ -37,30 +35,24 @@ impl BasicBlockOptimizer for FixedWindowProcessor { } } -impl FixedWindowProcessor { - /// Create a new `FixedWindowProcessor` with the given `optimizer`. +impl WindowProcessor { + /// Create a new `WindowProcessor` with the given `optimizer`. pub fn new(optimizer: T) -> Self { Self(optimizer) } - /// Run a single pass of fixed window peephole optimization on the given basic `block`. + /// Run a single pass of the window peephole optimization on the given basic `block`. /// If the block cannot be optimized further, return `None`. fn optimize_single_pass(&self, block: &[Bytecode]) -> Option> { - let window_size = self.0.fixed_window_size(); let mut changed = false; let mut new_block: Vec = vec![]; let mut left = 0; while left < block.len() { - let right = left + window_size; - if right > block.len() { - // At the end, not enough instructions to form a fixed window. - new_block.extend(block[left..].to_vec()); - break; - } - let window = &block[left..right]; - if let Some(optimized_window) = self.0.optimize_fixed_window(window) { + let window = &block[left..]; + if let Some((optimized_window, consumed)) = self.0.optimize_window(window) { + debug_assert!(consumed != 0); new_block.extend(optimized_window); - left = right; + left += consumed; changed = true; } else { new_block.push(block[left].clone()); diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/reducible_pairs.rs b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/reducible_pairs.rs index 4b41c12130323..ed6813e4196fa 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/reducible_pairs.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/peephole_optimizer/reducible_pairs.rs @@ -1,7 +1,7 @@ // Copyright (c) Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -//! This module contains a fixed window peephole optimizer for the Move bytecode. +//! This module contains a window peephole optimizer for the Move bytecode. //! As with all peephole optimizers here, it assumes that the bytecode is valid. //! //! We consider fixed windows of size 2 for this optimizer. @@ -39,31 +39,35 @@ //! Finally, note that fixed window optimizations are performed on windows within a basic //! block, not spanning across multiple basic blocks. -use crate::file_format_generator::peephole_optimizer::optimizers::FixedWindowOptimizer; +use crate::file_format_generator::peephole_optimizer::optimizers::WindowOptimizer; use move_binary_format::file_format::Bytecode; pub struct ReduciblePairs; -impl FixedWindowOptimizer for ReduciblePairs { - fn fixed_window_size(&self) -> usize { - 2 - } +impl ReduciblePairs { + const WINDOW_SIZE: usize = 2; +} - fn optimize_fixed_window(&self, window: &[Bytecode]) -> Option> { +impl WindowOptimizer for ReduciblePairs { + fn optimize_window(&self, window: &[Bytecode]) -> Option<(Vec, usize)> { use Bytecode::*; + if window.len() < Self::WINDOW_SIZE { + return None; + } // See module documentation for the reasoning behind these optimizations. - match (&window[0], &window[1]) { + let optimized = match (&window[0], &window[1]) { (StLoc(u), MoveLoc(v)) | (CopyLoc(u), StLoc(v)) | (MoveLoc(u), StLoc(v)) if *u == *v => { - Some(vec![]) + vec![] }, - (CopyLoc(_), Pop) => Some(vec![]), - (LdTrue, BrTrue(target)) | (LdFalse, BrFalse(target)) => Some(vec![Branch(*target)]), - (LdTrue, BrFalse(_)) | (LdFalse, BrTrue(_)) => Some(vec![]), - (Not, BrFalse(target)) => Some(vec![BrTrue(*target)]), - (Not, BrTrue(target)) => Some(vec![BrFalse(*target)]), - _ => None, - } + (CopyLoc(_), Pop) => vec![], + (LdTrue, BrTrue(target)) | (LdFalse, BrFalse(target)) => vec![Branch(*target)], + (LdTrue, BrFalse(_)) | (LdFalse, BrTrue(_)) => vec![], + (Not, BrFalse(target)) => vec![BrTrue(*target)], + (Not, BrTrue(target)) => vec![BrFalse(*target)], + _ => return None, + }; + Some((optimized, Self::WINDOW_SIZE)) } } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp index 202d6e5378226..e5a00ea3e8bf8 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp @@ -56,16 +56,14 @@ B0: 3: Pack[1](S) 4: StLoc[0](loc0: S) 5: MutBorrowLoc[0](loc0: S) - 6: LdU64(42) - 7: StLoc[1](loc1: u64) - 8: MutBorrowField[0](S.g: T) - 9: MutBorrowField[1](T.h: u64) - 10: StLoc[3](loc3: &mut u64) - 11: MoveLoc[1](loc1: u64) - 12: MoveLoc[3](loc3: &mut u64) - 13: WriteRef - 14: MoveLoc[0](loc0: S) - 15: Ret + 6: MutBorrowField[0](S.g: T) + 7: MutBorrowField[1](T.h: u64) + 8: StLoc[3](loc3: &mut u64) + 9: LdU64(42) + 10: MoveLoc[3](loc3: &mut u64) + 11: WriteRef + 12: MoveLoc[0](loc0: S) + 13: Ret } write_param(Arg0: &mut S) /* def_idx: 4 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp index 326fea066b89e..a923eb6daffcf 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp @@ -45,15 +45,13 @@ L3: loc1: &mut u64 B0: 0: MoveLoc[0](Arg0: address) 1: MutBorrowGlobal[0](R) - 2: LdU64(2) - 3: StLoc[1](Arg1: u64) - 4: MutBorrowField[0](R.f: u64) - 5: StLoc[3](loc1: &mut u64) - 6: MoveLoc[1](Arg1: u64) - 7: MoveLoc[3](loc1: &mut u64) - 8: WriteRef - 9: LdU64(9) - 10: Ret + 2: MutBorrowField[0](R.f: u64) + 3: StLoc[3](loc1: &mut u64) + 4: LdU64(2) + 5: MoveLoc[3](loc1: &mut u64) + 6: WriteRef + 7: LdU64(9) + 8: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp index f88ec059166e4..a75676beab4a8 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp @@ -11,14 +11,12 @@ B0: public test(Arg0: u64) /* def_idx: 1 */ { L1: loc0: u64 B0: - 0: LdU64(1) - 1: StLoc[1](loc0: u64) - 2: CopyLoc[0](Arg0: u64) - 3: CopyLoc[0](Arg0: u64) - 4: MoveLoc[1](loc0: u64) - 5: MoveLoc[0](Arg0: u64) - 6: Call consume(u64, u64, u64, u64) - 7: Ret + 0: CopyLoc[0](Arg0: u64) + 1: CopyLoc[0](Arg0: u64) + 2: LdU64(1) + 3: MoveLoc[0](Arg0: u64) + 4: Call consume(u64, u64, u64, u64) + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp new file mode 100644 index 0000000000000..d036275676863 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp @@ -0,0 +1,109 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +consume(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +public test01(Arg0: u64) /* def_idx: 1 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(3) + 3: LdU64(4) + 4: LdU64(5) + 5: StLoc[1](loc0: u64) + 6: StLoc[2](loc1: u64) + 7: StLoc[3](loc2: u64) + 8: StLoc[4](loc3: u64) + 9: StLoc[5](loc4: u64) + 10: MoveLoc[0](Arg0: u64) + 11: MoveLoc[5](loc4: u64) + 12: MoveLoc[4](loc3: u64) + 13: MoveLoc[3](loc2: u64) + 14: MoveLoc[2](loc1: u64) + 15: MoveLoc[1](loc0: u64) + 16: Call consume(u64, u64, u64, u64, u64, u64) + 17: Ret +} +public test02(Arg0: u64) /* def_idx: 2 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(4) + 3: LdU64(5) + 4: StLoc[1](loc0: u64) + 5: StLoc[2](loc1: u64) + 6: StLoc[3](loc2: u64) + 7: StLoc[4](loc3: u64) + 8: CopyLoc[0](Arg0: u64) + 9: MoveLoc[4](loc3: u64) + 10: MoveLoc[3](loc2: u64) + 11: MoveLoc[0](Arg0: u64) + 12: MoveLoc[2](loc1: u64) + 13: MoveLoc[1](loc0: u64) + 14: Call consume(u64, u64, u64, u64, u64, u64) + 15: Ret +} +public test03(Arg0: u64) /* def_idx: 3 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +L6: loc5: u64 +L7: loc6: u64 +L8: loc7: u64 +L9: loc8: u64 +L10: loc9: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(3) + 3: LdU64(4) + 4: LdU64(5) + 5: StLoc[1](loc0: u64) + 6: StLoc[2](loc1: u64) + 7: StLoc[3](loc2: u64) + 8: StLoc[4](loc3: u64) + 9: StLoc[5](loc4: u64) + 10: CopyLoc[0](Arg0: u64) + 11: MoveLoc[5](loc4: u64) + 12: MoveLoc[4](loc3: u64) + 13: MoveLoc[3](loc2: u64) + 14: MoveLoc[2](loc1: u64) + 15: MoveLoc[1](loc0: u64) + 16: Call consume(u64, u64, u64, u64, u64, u64) + 17: LdU64(1) + 18: LdU64(2) + 19: LdU64(3) + 20: LdU64(4) + 21: LdU64(5) + 22: StLoc[6](loc5: u64) + 23: StLoc[7](loc6: u64) + 24: StLoc[8](loc7: u64) + 25: StLoc[9](loc8: u64) + 26: StLoc[10](loc9: u64) + 27: MoveLoc[0](Arg0: u64) + 28: MoveLoc[10](loc9: u64) + 29: MoveLoc[9](loc8: u64) + 30: MoveLoc[8](loc7: u64) + 31: MoveLoc[7](loc6: u64) + 32: MoveLoc[6](loc5: u64) + 33: Call consume(u64, u64, u64, u64, u64, u64) + 34: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.move b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.move new file mode 100644 index 0000000000000..3c85242b9d4cd --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.move @@ -0,0 +1,16 @@ +module 0xc0ffee::m { + fun consume(_a: u64, _b: u64, _c: u64, _d: u64, _e: u64, _f: u64) {} + + public fun test01(a: u64) { + consume(a, 1, 2, 3, 4, 5); + } + + public fun test02(a: u64) { + consume(a, 1, 2, a, 4, 5); + } + + public fun test03(a: u64) { + consume(a, 1, 2, 3, 4, 5); + consume(a, 1, 2, 3, 4, 5); + } +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp new file mode 100644 index 0000000000000..8503b6e5d38c3 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp @@ -0,0 +1,66 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +consume(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +public test01(Arg0: u64) /* def_idx: 1 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +B0: + 0: MoveLoc[0](Arg0: u64) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume(u64, u64, u64, u64, u64, u64) + 7: Ret +} +public test02(Arg0: u64) /* def_idx: 2 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +B0: + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(1) + 2: LdU64(2) + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume(u64, u64, u64, u64, u64, u64) + 7: Ret +} +public test03(Arg0: u64) /* def_idx: 3 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +B0: + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume(u64, u64, u64, u64, u64, u64) + 7: MoveLoc[0](Arg0: u64) + 8: LdU64(1) + 9: LdU64(2) + 10: LdU64(3) + 11: LdU64(4) + 12: LdU64(5) + 13: Call consume(u64, u64, u64, u64, u64, u64) + 14: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp new file mode 100644 index 0000000000000..07e0c3132d79f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp @@ -0,0 +1,180 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { +struct S { + x: u64 +} + +consume1(Arg0: &S, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64) /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: Pop + 2: Ret +} +consume2(Arg0: &S, Arg1: u64, Arg2: u64, Arg3: &S, Arg4: u64, Arg5: u64) /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: Pop + 2: MoveLoc[3](Arg3: &S) + 3: Pop + 4: Ret +} +consume3(Arg0: &S, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: &u64, Arg5: u64) /* def_idx: 2 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: Pop + 2: MoveLoc[4](Arg4: &u64) + 3: Pop + 4: Ret +} +public test01(Arg0: &S) /* def_idx: 3 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(3) + 3: LdU64(4) + 4: LdU64(5) + 5: StLoc[1](loc0: u64) + 6: StLoc[2](loc1: u64) + 7: StLoc[3](loc2: u64) + 8: StLoc[4](loc3: u64) + 9: StLoc[5](loc4: u64) + 10: MoveLoc[0](Arg0: &S) + 11: MoveLoc[5](loc4: u64) + 12: MoveLoc[4](loc3: u64) + 13: MoveLoc[3](loc2: u64) + 14: MoveLoc[2](loc1: u64) + 15: MoveLoc[1](loc0: u64) + 16: Call consume1(&S, u64, u64, u64, u64, u64) + 17: Ret +} +public test02(Arg0: &S) /* def_idx: 4 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(4) + 3: LdU64(5) + 4: StLoc[1](loc0: u64) + 5: StLoc[2](loc1: u64) + 6: StLoc[3](loc2: u64) + 7: StLoc[4](loc3: u64) + 8: CopyLoc[0](Arg0: &S) + 9: MoveLoc[4](loc3: u64) + 10: MoveLoc[3](loc2: u64) + 11: MoveLoc[0](Arg0: &S) + 12: MoveLoc[2](loc1: u64) + 13: MoveLoc[1](loc0: u64) + 14: Call consume2(&S, u64, u64, &S, u64, u64) + 15: Ret +} +public test03(Arg0: &S) /* def_idx: 5 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +L6: loc5: u64 +L7: loc6: u64 +L8: loc7: u64 +L9: loc8: u64 +L10: loc9: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(3) + 3: LdU64(4) + 4: LdU64(5) + 5: StLoc[1](loc0: u64) + 6: StLoc[2](loc1: u64) + 7: StLoc[3](loc2: u64) + 8: StLoc[4](loc3: u64) + 9: StLoc[5](loc4: u64) + 10: CopyLoc[0](Arg0: &S) + 11: MoveLoc[5](loc4: u64) + 12: MoveLoc[4](loc3: u64) + 13: MoveLoc[3](loc2: u64) + 14: MoveLoc[2](loc1: u64) + 15: MoveLoc[1](loc0: u64) + 16: Call consume1(&S, u64, u64, u64, u64, u64) + 17: LdU64(1) + 18: LdU64(2) + 19: LdU64(3) + 20: LdU64(4) + 21: LdU64(5) + 22: StLoc[6](loc5: u64) + 23: StLoc[7](loc6: u64) + 24: StLoc[8](loc7: u64) + 25: StLoc[9](loc8: u64) + 26: StLoc[10](loc9: u64) + 27: MoveLoc[0](Arg0: &S) + 28: MoveLoc[10](loc9: u64) + 29: MoveLoc[9](loc8: u64) + 30: MoveLoc[8](loc7: u64) + 31: MoveLoc[7](loc6: u64) + 32: MoveLoc[6](loc5: u64) + 33: Call consume1(&S, u64, u64, u64, u64, u64) + 34: Ret +} +public test04(Arg0: &S) /* def_idx: 6 */ { +L1: loc0: u64 +L2: loc1: &u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +L6: loc5: u64 +L7: loc6: u64 +L8: loc7: u64 +L9: loc8: u64 +L10: loc9: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(3) + 3: CopyLoc[0](Arg0: &S) + 4: ImmBorrowField[0](S.x: u64) + 5: LdU64(5) + 6: StLoc[1](loc0: u64) + 7: StLoc[2](loc1: &u64) + 8: StLoc[3](loc2: u64) + 9: StLoc[4](loc3: u64) + 10: StLoc[5](loc4: u64) + 11: CopyLoc[0](Arg0: &S) + 12: MoveLoc[5](loc4: u64) + 13: MoveLoc[4](loc3: u64) + 14: MoveLoc[3](loc2: u64) + 15: MoveLoc[2](loc1: &u64) + 16: MoveLoc[1](loc0: u64) + 17: Call consume3(&S, u64, u64, u64, &u64, u64) + 18: LdU64(1) + 19: LdU64(2) + 20: LdU64(3) + 21: CopyLoc[0](Arg0: &S) + 22: ImmBorrowField[0](S.x: u64) + 23: ReadRef + 24: LdU64(5) + 25: StLoc[6](loc5: u64) + 26: StLoc[7](loc6: u64) + 27: StLoc[8](loc7: u64) + 28: StLoc[9](loc8: u64) + 29: StLoc[10](loc9: u64) + 30: MoveLoc[0](Arg0: &S) + 31: MoveLoc[10](loc9: u64) + 32: MoveLoc[9](loc8: u64) + 33: MoveLoc[8](loc7: u64) + 34: MoveLoc[7](loc6: u64) + 35: MoveLoc[6](loc5: u64) + 36: Call consume1(&S, u64, u64, u64, u64, u64) + 37: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.move b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.move new file mode 100644 index 0000000000000..af26fbee6e00b --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.move @@ -0,0 +1,29 @@ +module 0xc0ffee::m { + struct S { + x: u64, + } + + fun consume1(_a: &S, _b: u64, _c: u64, _d: u64, _e: u64, _f: u64) {} + + fun consume2(_a: &S, _b: u64, _c: u64, _d: &S, _e: u64, _f: u64) {} + + fun consume3(_a: &S, _b: u64, _c: u64, _d: u64, _e: &u64, _f: u64) {} + + public fun test01(a: &S) { + consume1(a, 1, 2, 3, 4, 5); + } + + public fun test02(a: &S) { + consume2(a, 1, 2, a, 4, 5); + } + + public fun test03(a: &S) { + consume1(a, 1, 2, 3, 4, 5); + consume1(a, 1, 2, 3, 4, 5); + } + + public fun test04(a: &S) { + consume3(a, 1, 2, 3, &a.x, 5); + consume1(a, 1, 2, 3, a.x, 5); + } +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp new file mode 100644 index 0000000000000..790b06577f4a9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp @@ -0,0 +1,129 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { +struct S { + x: u64 +} + +consume1(Arg0: &S, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64) /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: Pop + 2: Ret +} +consume2(Arg0: &S, Arg1: u64, Arg2: u64, Arg3: &S, Arg4: u64, Arg5: u64) /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: Pop + 2: MoveLoc[3](Arg3: &S) + 3: Pop + 4: Ret +} +consume3(Arg0: &S, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: &u64, Arg5: u64) /* def_idx: 2 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: Pop + 2: MoveLoc[4](Arg4: &u64) + 3: Pop + 4: Ret +} +public test01(Arg0: &S) /* def_idx: 3 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +B0: + 0: MoveLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume1(&S, u64, u64, u64, u64, u64) + 7: Ret +} +public test02(Arg0: &S) /* def_idx: 4 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +B0: + 0: CopyLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: MoveLoc[0](Arg0: &S) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume2(&S, u64, u64, &S, u64, u64) + 7: Ret +} +public test03(Arg0: &S) /* def_idx: 5 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +B0: + 0: CopyLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume1(&S, u64, u64, u64, u64, u64) + 7: MoveLoc[0](Arg0: &S) + 8: LdU64(1) + 9: LdU64(2) + 10: LdU64(3) + 11: LdU64(4) + 12: LdU64(5) + 13: Call consume1(&S, u64, u64, u64, u64, u64) + 14: Ret +} +public test04(Arg0: &S) /* def_idx: 6 */ { +L1: loc0: u64 +L2: loc1: &u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +L6: loc5: u64 +B0: + 0: LdU64(1) + 1: LdU64(2) + 2: LdU64(3) + 3: CopyLoc[0](Arg0: &S) + 4: ImmBorrowField[0](S.x: u64) + 5: StLoc[2](loc1: &u64) + 6: StLoc[3](loc2: u64) + 7: StLoc[4](loc3: u64) + 8: StLoc[5](loc4: u64) + 9: CopyLoc[0](Arg0: &S) + 10: MoveLoc[5](loc4: u64) + 11: MoveLoc[4](loc3: u64) + 12: MoveLoc[3](loc2: u64) + 13: MoveLoc[2](loc1: &u64) + 14: LdU64(5) + 15: Call consume3(&S, u64, u64, u64, &u64, u64) + 16: LdU64(1) + 17: LdU64(2) + 18: LdU64(3) + 19: CopyLoc[0](Arg0: &S) + 20: ImmBorrowField[0](S.x: u64) + 21: ReadRef + 22: StLoc[1](loc0: u64) + 23: StLoc[3](loc2: u64) + 24: StLoc[4](loc3: u64) + 25: StLoc[5](loc4: u64) + 26: MoveLoc[0](Arg0: &S) + 27: MoveLoc[5](loc4: u64) + 28: MoveLoc[4](loc3: u64) + 29: MoveLoc[3](loc2: u64) + 30: MoveLoc[1](loc0: u64) + 31: LdU64(5) + 32: Call consume1(&S, u64, u64, u64, u64, u64) + 33: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp new file mode 100644 index 0000000000000..42e76e110a911 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp @@ -0,0 +1,34 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +bar(Arg0: &mut u64) /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &mut u64) + 1: Pop + 2: Ret +} +baz(Arg0: u64, Arg1: u64, Arg2: u64) /* def_idx: 1 */ { +B0: + 0: Ret +} +public foo(Arg0: u64) /* def_idx: 2 */ { +L1: loc0: u64 +L2: loc1: u64 +B0: + 0: MutBorrowLoc[0](Arg0: u64) + 1: Call bar(&mut u64) + 2: LdU64(1) + 3: LdU64(2) + 4: StLoc[1](loc0: u64) + 5: StLoc[2](loc1: u64) + 6: MoveLoc[0](Arg0: u64) + 7: MoveLoc[2](loc1: u64) + 8: MoveLoc[1](loc0: u64) + 9: Call baz(u64, u64, u64) + 10: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.move b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.move new file mode 100644 index 0000000000000..d984fdb5ab76f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.move @@ -0,0 +1,10 @@ +module 0xc0ffee::m { + fun bar(_x: &mut u64) {} + + fun baz(_x: u64, _y: u64, _z: u64) {} + + public fun foo(x: u64) { + bar(&mut x); + baz(x, 1, 2); + } +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp new file mode 100644 index 0000000000000..33b1f294dc099 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp @@ -0,0 +1,30 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +bar(Arg0: &mut u64) /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &mut u64) + 1: Pop + 2: Ret +} +baz(Arg0: u64, Arg1: u64, Arg2: u64) /* def_idx: 1 */ { +B0: + 0: Ret +} +public foo(Arg0: u64) /* def_idx: 2 */ { +L1: loc0: u64 +L2: loc1: u64 +B0: + 0: MutBorrowLoc[0](Arg0: u64) + 1: Call bar(&mut u64) + 2: MoveLoc[0](Arg0: u64) + 3: LdU64(1) + 4: LdU64(2) + 5: Call baz(u64, u64, u64) + 6: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp new file mode 100644 index 0000000000000..3afc5c9ca65d3 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp @@ -0,0 +1,56 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +consume1(Arg0: u64, Arg1: u64, Arg2: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +one(): u64 /* def_idx: 1 */ { +B0: + 0: LdU64(1) + 1: Ret +} +public test1(Arg0: u64) /* def_idx: 2 */ { +L1: loc0: u64 +B0: + 0: LdU64(1) + 1: StLoc[1](loc0: u64) + 2: CopyLoc[0](Arg0: u64) + 3: MoveLoc[0](Arg0: u64) + 4: MoveLoc[1](loc0: u64) + 5: Call consume1(u64, u64, u64) + 6: Ret +} +public test2(Arg0: u64) /* def_idx: 3 */ { +L1: loc0: u64 +L2: loc1: u64 +B0: + 0: Call one(): u64 + 1: LdU64(2) + 2: StLoc[1](loc0: u64) + 3: StLoc[2](loc1: u64) + 4: MoveLoc[2](loc1: u64) + 5: MoveLoc[0](Arg0: u64) + 6: MoveLoc[1](loc0: u64) + 7: Call consume1(u64, u64, u64) + 8: Ret +} +public test3(Arg0: u64) /* def_idx: 4 */ { +L1: loc0: u64 +L2: loc1: u64 +B0: + 0: Call one(): u64 + 1: LdU64(3) + 2: StLoc[1](loc0: u64) + 3: StLoc[2](loc1: u64) + 4: MoveLoc[0](Arg0: u64) + 5: MoveLoc[2](loc1: u64) + 6: MoveLoc[1](loc0: u64) + 7: Call consume1(u64, u64, u64) + 8: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.move b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.move new file mode 100644 index 0000000000000..40c32e4534d91 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.move @@ -0,0 +1,22 @@ +module 0xc0ffee::m { + fun consume1(_a: u64, _b: u64, _c: u64) {} + + fun one(): u64 { + 1 + } + + public fun test1(p: u64) { + consume1(p, p, 1); + } + + public fun test2(p: u64) { + let q = one(); + consume1(q, p, 2); + } + + public fun test3(p: u64) { + let q = one(); + consume1(p, q, 3); + } + +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp new file mode 100644 index 0000000000000..56cc7a5deab9c --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp @@ -0,0 +1,48 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +consume1(Arg0: u64, Arg1: u64, Arg2: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +one(): u64 /* def_idx: 1 */ { +B0: + 0: LdU64(1) + 1: Ret +} +public test1(Arg0: u64) /* def_idx: 2 */ { +L1: loc0: u64 +B0: + 0: CopyLoc[0](Arg0: u64) + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(1) + 3: Call consume1(u64, u64, u64) + 4: Ret +} +public test2(Arg0: u64) /* def_idx: 3 */ { +L1: loc0: u64 +L2: loc1: u64 +B0: + 0: Call one(): u64 + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(2) + 3: Call consume1(u64, u64, u64) + 4: Ret +} +public test3(Arg0: u64) /* def_idx: 4 */ { +L1: loc0: u64 +L2: loc1: u64 +B0: + 0: Call one(): u64 + 1: StLoc[2](loc1: u64) + 2: MoveLoc[0](Arg0: u64) + 3: MoveLoc[2](loc1: u64) + 4: LdU64(3) + 5: Call consume1(u64, u64, u64) + 6: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp index 9fa99dc7109a1..e42136755a54d 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp @@ -24,14 +24,12 @@ L2: loc1: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: Call foo(u64): u64 * u64 - 2: LdU64(0) - 3: StLoc[1](loc0: u64) - 4: StLoc[0](Arg0: u64) - 5: MoveLoc[1](loc0: u64) - 6: Eq - 7: BrFalse(0) + 2: StLoc[0](Arg0: u64) + 3: LdU64(0) + 4: Eq + 5: BrFalse(0) B1: - 8: Ret + 6: Ret } public test2(Arg0: u64) /* def_idx: 2 */ { L1: loc0: bool diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.off.exp index fa261282e82ed..80f5dfb218a9f 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.off.exp @@ -23,21 +23,19 @@ B0: 0: Call one(): u64 1: Call one(): u64 2: Call one(): u64 - 3: LdU64(0) - 4: StLoc[0](loc0: u64) - 5: StLoc[1](loc1: u64) - 6: MoveLoc[0](loc0: u64) - 7: Eq - 8: StLoc[3](loc3: bool) - 9: StLoc[4](loc4: u64) - 10: MoveLoc[3](loc3: bool) - 11: BrFalse(13) + 3: StLoc[1](loc1: u64) + 4: LdU64(0) + 5: Eq + 6: StLoc[3](loc3: bool) + 7: StLoc[4](loc4: u64) + 8: MoveLoc[3](loc3: bool) + 9: BrFalse(11) B1: - 12: Call bar() + 10: Call bar() B2: - 13: MoveLoc[4](loc4: u64) - 14: MoveLoc[1](loc1: u64) - 15: Ret + 11: MoveLoc[4](loc4: u64) + 12: MoveLoc[1](loc1: u64) + 13: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.off.exp index dfded55aae409..a4dfa90b2ba3c 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.off.exp @@ -22,31 +22,29 @@ L2: loc2: u64 L3: loc3: u64 B0: 0: Call foo(): u64 * u64 * u64 - 1: LdU64(0) - 2: StLoc[0](loc0: u64) - 3: StLoc[1](loc1: u64) - 4: StLoc[2](loc2: u64) - 5: MoveLoc[0](loc0: u64) - 6: Eq - 7: BrFalse(9) + 1: StLoc[1](loc1: u64) + 2: StLoc[2](loc2: u64) + 3: LdU64(0) + 4: Eq + 5: BrFalse(7) B1: - 8: Call bar() + 6: Call bar() B2: - 9: MoveLoc[2](loc2: u64) - 10: LdU64(0) - 11: Eq - 12: BrFalse(14) + 7: MoveLoc[2](loc2: u64) + 8: LdU64(0) + 9: Eq + 10: BrFalse(12) B3: - 13: Call bar() + 11: Call bar() B4: - 14: MoveLoc[1](loc1: u64) - 15: LdU64(0) - 16: Eq - 17: BrFalse(19) + 12: MoveLoc[1](loc1: u64) + 13: LdU64(0) + 14: Eq + 15: BrFalse(17) B5: - 18: Call bar() + 16: Call bar() B6: - 19: Ret + 17: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/write_ref_01.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/write_ref_01.off.exp index 895763f342145..4b438fa00127b 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/write_ref_01.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/write_ref_01.off.exp @@ -9,13 +9,11 @@ L1: loc0: u64 L2: loc1: &mut u64 B0: 0: MutBorrowLoc[0](Arg0: u64) - 1: LdU64(42) - 2: StLoc[1](loc0: u64) - 3: StLoc[2](loc1: &mut u64) - 4: MoveLoc[1](loc0: u64) - 5: MoveLoc[2](loc1: &mut u64) - 6: WriteRef - 7: Ret + 1: StLoc[2](loc1: &mut u64) + 2: LdU64(42) + 3: MoveLoc[2](loc1: &mut u64) + 4: WriteRef + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp index e96b4b2606af0..c1d0ebf04aff7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp @@ -125,17 +125,13 @@ L1: loc1: u64 L2: loc2: u64 B0: 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(1) - 3: StLoc[0](loc0: u64) - 4: StLoc[1](loc1: u64) - 5: MoveLoc[0](loc0: u64) + 1: LdU64(1) + 2: Add + 3: StLoc[2](loc2: u64) + 4: LdU64(2) + 5: MoveLoc[2](loc2: u64) 6: Add - 7: StLoc[2](loc2: u64) - 8: MoveLoc[1](loc1: u64) - 9: MoveLoc[2](loc2: u64) - 10: Add - 11: Ret + 7: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp index 3430fdcadc2db..bdbed18eca8eb 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp @@ -126,15 +126,11 @@ L1: loc1: u64 L2: loc2: u64 B0: 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(1) - 3: StLoc[0](loc0: u64) - 4: StLoc[1](loc1: u64) - 5: MoveLoc[0](loc0: u64) - 6: Add - 7: Pop - 8: MoveLoc[1](loc1: u64) - 9: Ret + 1: LdU64(1) + 2: Add + 3: Pop + 4: LdU64(2) + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp index d5ab5ce583778..6a7fe387fea8d 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp @@ -106,12 +106,10 @@ L0: loc0: u64 B0: 0: LdU64(1) 1: LdU64(2) - 2: LdU64(3) - 3: StLoc[0](loc0: u64) + 2: Add + 3: LdU64(3) 4: Add - 5: MoveLoc[0](loc0: u64) - 6: Add - 7: Ret + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp index f1f1887b1687c..1910043c0413b 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp @@ -100,12 +100,10 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { L0: loc0: u64 B0: - 0: LdU64(2) - 1: StLoc[0](loc0: u64) - 2: LdU64(9) - 3: MoveLoc[0](loc0: u64) - 4: Add - 5: Ret + 0: LdU64(9) + 1: LdU64(2) + 2: Add + 3: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.optimize-no-simplify.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.optimize-no-simplify.exp index 2d377179b54a4..1352cb7967ab0 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.optimize-no-simplify.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.optimize-no-simplify.exp @@ -27,5 +27,5 @@ Error: Function execution failed with VMError: { sub_status: None, location: 0x42::m, indices: [], - offsets: [(FunctionDefinitionIndex(5), 7)], + offsets: [(FunctionDefinitionIndex(5), 5)], } diff --git a/third_party/move/move-prover/bytecode-pipeline/tests/data_invariant_instrumentation/pack.v2_exp b/third_party/move/move-prover/bytecode-pipeline/tests/data_invariant_instrumentation/pack.v2_exp new file mode 100644 index 0000000000000..572e482b9d868 --- /dev/null +++ b/third_party/move/move-prover/bytecode-pipeline/tests/data_invariant_instrumentation/pack.v2_exp @@ -0,0 +1,36 @@ +============ initial translation from Move ================ + +[variant baseline] +public fun Test::test_pack(): Test::R { + var $t0: u64 + var $t1: u64 + var $t2: Test::S + var $t3: Test::R + 0: $t0 := 3 + 1: $t1 := 1 + 2: $t2 := pack Test::S($t1) + 3: $t3 := pack Test::R($t0, $t2) + 4: return $t3 +} + +============ after pipeline `data_invariant_instrumentation` ================ + +[variant verification] +public fun Test::test_pack(): Test::R { + var $t0: u64 + var $t1: u64 + var $t2: Test::S + var $t3: Test::R + 0: $t0 := 3 + 1: $t1 := 1 + 2: $t2 := pack Test::S($t1) + # data invariant at tests/data_invariant_instrumentation/pack.move:16:9+16 + # VC: data invariant does not hold at tests/data_invariant_instrumentation/pack.move:16:9+16 + 3: assert Gt(select Test::S.y($t2), 0) + 4: $t3 := pack Test::R($t0, $t2) + # data invariant at tests/data_invariant_instrumentation/pack.move:12:9+18 + # VC: data invariant does not hold at tests/data_invariant_instrumentation/pack.move:12:9+18 + 5: assert Gt(select Test::R.x($t3), select Test::S.y(select Test::R.s($t3))) + 6: label L1 + 7: return $t3 +} diff --git a/third_party/move/move-prover/tests/sources/functional/enum_abort.v2_exp b/third_party/move/move-prover/tests/sources/functional/enum_abort.v2_exp index 86dc4d5cb2bf9..4f2cdf6e909ca 100644 --- a/third_party/move/move-prover/tests/sources/functional/enum_abort.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/enum_abort.v2_exp @@ -81,7 +81,7 @@ error: abort not covered by any of the `aborts_if` clauses ┌─ tests/sources/functional/enum_abort.move:129:5 │ 123 │ abort 30 // aborts - │ -------- abort happened here with code 0x1E + │ -- abort happened here with code 0x1E · 129 │ ╭ spec test_match_abort { 130 │ │ aborts_if false; @@ -107,6 +107,5 @@ error: abort not covered by any of the `aborts_if` clauses = at tests/sources/functional/enum_abort.move:122: test_match_abort = = = at tests/sources/functional/enum_abort.move:122: test_match_abort - = = = at tests/sources/functional/enum_abort.move:123: test_match_abort = ABORTED diff --git a/third_party/move/move-prover/tests/sources/functional/generic_invariants.v2_exp b/third_party/move/move-prover/tests/sources/functional/generic_invariants.v2_exp index f54c9561cdf7f..c7cf84cf92fe9 100644 --- a/third_party/move/move-prover/tests/sources/functional/generic_invariants.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/generic_invariants.v2_exp @@ -12,7 +12,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:11: publish_u64_bool - = = = at tests/sources/functional/generic_invariants.move:34 error: global memory invariant does not hold @@ -28,7 +27,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:16: publish_u64_y - = = = at tests/sources/functional/generic_invariants.move:34 error: global memory invariant does not hold @@ -44,7 +42,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:21: publish_x_bool - = = = at tests/sources/functional/generic_invariants.move:34 error: global memory invariant does not hold @@ -60,7 +57,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:26: publish_x_y - = = = at tests/sources/functional/generic_invariants.move:34 error: global memory invariant does not hold @@ -76,7 +72,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:11: publish_u64_bool - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 @@ -93,7 +88,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:16: publish_u64_y - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 @@ -110,7 +104,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:21: publish_x_bool - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 @@ -127,7 +120,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:26: publish_x_y - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 @@ -144,7 +136,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:11: publish_u64_bool - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 @@ -162,7 +153,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:16: publish_u64_y - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 @@ -180,7 +170,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:21: publish_x_bool - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 @@ -198,7 +187,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:26: publish_x_y - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 @@ -216,7 +204,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:11: publish_u64_bool - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 @@ -235,7 +222,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:16: publish_u64_y - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 @@ -254,7 +240,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:21: publish_x_bool - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 @@ -273,7 +258,6 @@ error: global memory invariant does not hold = x = = y = = at tests/sources/functional/generic_invariants.move:26: publish_x_y - = = = at tests/sources/functional/generic_invariants.move:34 = at tests/sources/functional/generic_invariants.move:39 = at tests/sources/functional/generic_invariants.move:44 diff --git a/third_party/move/scripts/compare_num_instructions.py b/third_party/move/scripts/compare_num_instructions.py index 8911182d20048..6c4b82224429f 100755 --- a/third_party/move/scripts/compare_num_instructions.py +++ b/third_party/move/scripts/compare_num_instructions.py @@ -41,7 +41,7 @@ def main(): # Build the move-disassembler in release mode. subprocess.run(["cargo", "build", "--release", "-p", "move-disassembler"]) (total_1, total_2) = (0, 0) # Total number of instructions. - tally = [] # List of tuples containing the percentage increase and the file name. + tally = [] # List of tuples containing the net increase and the file name. common_path = os.path.commonpath([dir1, dir2]) # Compute for all bytecode files in the build folders. for file1 in glob.glob(dir1 + "/**/*.mv", recursive=True): @@ -50,17 +50,17 @@ def main(): print(f"There is no file comparable to {file1} in {dir2}") sys.exit(1) (i1, i2) = (count_instructions(file1), count_instructions(file2)) - percent_inc = percentage_change(i1, i2) - tally.append((percent_inc, file1.removeprefix(common_path))) + net_increase = i2 - i1 + tally.append((net_increase, file1.removeprefix(common_path))) total_1 += i1 total_2 += i2 # Print the results per file, in order of higher increase earlier. - for percent_inc, file in sorted(tally, reverse=True): - print(f"{file}: {percent_inc:.1f}%") + for net_increase, file in sorted(tally, reverse=True): + print(f"{file}: {net_increase}") # Print the total percentage increase across all files. percent_inc = percentage_change(total_1, total_2) print( - f"Total percentage change in instructions: {percent_inc:.1f}%, {total_1} -> {total_2}" + f"Total percentage increase in instructions: {percent_inc:.1f}%, going from {total_1} -> {total_2}, with net increase of: {total_2 - total_1}" ) # Change back to the original working directory. os.chdir(original_working_dir) @@ -69,7 +69,7 @@ def main(): def percentage_change(i1, i2): """Percentage change from `i1` to `i2`.""" if i1 != 0: - return ((i1 - i2) * 100.0) / i1 + return ((i2 - i1) * 100.0) / i1 return 0