From df3e5672e3c890094f3af5352a8216579aa874ac Mon Sep 17 00:00:00 2001 From: Teng Zhang Date: Sat, 6 Jul 2024 10:55:26 -0700 Subject: [PATCH] fix (#13907) --- .../src/bytecode_generator.rs | 8 +- .../borrow_deref_optimize.exp | 117 ++++++++++++++++++ .../borrow_deref_optimize.move | 29 +++++ 3 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp create mode 100644 third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.move diff --git a/third_party/move/move-compiler-v2/src/bytecode_generator.rs b/third_party/move/move-compiler-v2/src/bytecode_generator.rs index 1d95b873416c0..e26177acf6055 100644 --- a/third_party/move/move-compiler-v2/src/bytecode_generator.rs +++ b/third_party/move/move-compiler-v2/src/bytecode_generator.rs @@ -1079,7 +1079,13 @@ impl<'env> Generator<'env> { }, ExpData::Call(_arg_id, Operation::Deref, args) => { // Optimize `Borrow(Deref(x)) => x` - return self.gen(vec![target], &args[0]); + // only when `kind` is equal to the reference kind of `x` + let arg_type = self.env().get_node_type(args[0].node_id()); + if let Type::Reference(ref_kind, _) = arg_type { + if ref_kind == kind { + return self.gen(vec![target], &args[0]); + } + } }, ExpData::LocalVar(_arg_id, sym) => return self.gen_borrow_local(target, id, *sym), ExpData::Temporary(_arg_id, temp) => return self.gen_borrow_temp(target, id, *temp), diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp new file mode 100644 index 0000000000000..a80f9f4e4a890 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp @@ -0,0 +1,117 @@ +// -- Model dump before bytecode pipeline +module 0x42::test { + struct X { + value: bool, + } + private fun no_optimize_resource(): bool + acquires test::X(*) + { + { + let x: &mut test::X = Borrow(Mutable)(Deref(BorrowGlobal(Immutable)(0x1))); + select test::X.value<&mut test::X>(x) + } + } + private fun no_optimize_vector() { + { + let _: &mut u64 = vector::borrow_mut(Borrow(Mutable)(Deref(vector::borrow>(Borrow(Immutable)([Vector([Number(1), Number(2)])]), 0))), 1); + Tuple() + } + } + private fun optimize_resource(): bool + acquires test::X(*) + { + { + let x: &test::X = Borrow(Immutable)(Deref(BorrowGlobal(Immutable)(0x1))); + select test::X.value<&test::X>(x) + } + } + private fun optimize_vector() { + { + let x: vector> = [Vector([Number(1), Number(2)])]; + { + let _: &mut u64 = vector::borrow_mut(Borrow(Mutable)(Deref(vector::borrow_mut>(Borrow(Mutable)(x), 0))), 1); + Tuple() + } + } + } +} // end 0x42::test + +============ initial bytecode ================ + +[variant baseline] +fun test::no_optimize_resource(): bool { + var $t0: bool + var $t1: &mut test::X + var $t2: test::X + var $t3: &test::X + var $t4: address + var $t5: &bool + 0: $t4 := 0x1 + 1: $t3 := borrow_global($t4) + 2: $t2 := read_ref($t3) + 3: $t1 := borrow_local($t2) + 4: $t5 := borrow_field.value($t1) + 5: $t0 := read_ref($t5) + 6: return $t0 +} + + +[variant baseline] +fun test::no_optimize_vector() { + var $t0: &mut u64 + var $t1: &mut vector + var $t2: vector + var $t3: &vector + var $t4: &vector> + var $t5: vector> + var $t6: u64 + var $t7: u64 + var $t8: &mut u64 + 0: $t5 := ["[\"1\", \"2\"]"] + 1: $t4 := borrow_local($t5) + 2: $t6 := 0 + 3: $t3 := vector::borrow>($t4, $t6) + 4: $t2 := read_ref($t3) + 5: $t1 := borrow_local($t2) + 6: $t7 := 1 + 7: $t0 := vector::borrow_mut($t1, $t7) + 8: $t8 := infer($t0) + 9: return () +} + + +[variant baseline] +fun test::optimize_resource(): bool { + var $t0: bool + var $t1: &test::X + var $t2: address + var $t3: &bool + 0: $t2 := 0x1 + 1: $t1 := borrow_global($t2) + 2: $t3 := borrow_field.value($t1) + 3: $t0 := read_ref($t3) + 4: return $t0 +} + + +[variant baseline] +fun test::optimize_vector() { + var $t0: vector> + var $t1: &mut u64 + var $t2: &mut vector + var $t3: &mut vector> + var $t4: u64 + var $t5: u64 + var $t6: &mut u64 + 0: $t0 := ["[\"1\", \"2\"]"] + 1: $t3 := borrow_local($t0) + 2: $t4 := 0 + 3: $t2 := vector::borrow_mut>($t3, $t4) + 4: $t5 := 1 + 5: $t1 := vector::borrow_mut($t2, $t5) + 6: $t6 := infer($t1) + 7: return () +} + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.move b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.move new file mode 100644 index 0000000000000..6a84b1ef36246 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.move @@ -0,0 +1,29 @@ +module 0x42::test { + + fun no_optimize_vector() { + use std::vector; + let x = vector[vector[1, 2]]; + let _ = vector::borrow_mut(&mut (*vector::borrow(&x, 0)), 1); + } + + fun optimize_vector() { + use std::vector; + let x = vector[vector[1, 2]]; + let _ = vector::borrow_mut(&mut (*vector::borrow_mut(&mut x, 0)), 1); + } + + struct X has key, drop, copy { + value: bool + } + + fun no_optimize_resource(): bool acquires X { + let x = &mut (*borrow_global(@0x1)); + x.value + } + + fun optimize_resource(): bool acquires X { + let x = &(*borrow_global(@0x1)); + x.value + } + +}