Skip to content

Commit

Permalink
improve asm copy propagation for MOVE instruction (#6641)
Browse files Browse the repository at this point in the history
## Description

This PR improve value propagation optimization in two ways:

1 - First, when the optimizer knows that both source and destination
registers of the `MOVE` instruct have the same value and version; it
will remove the instruction as it is useless;
2 - Otherwise, we propagate the value saying that destination now have
the same value and version of the source register for other
optimizations.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [ ] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.
  • Loading branch information
xunilrj authored Nov 25, 2024
1 parent 64d1c6e commit bcd15c3
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 148 deletions.
8 changes: 4 additions & 4 deletions forc-plugins/forc-client/tests/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ async fn test_simple_deploy() {
node.kill().unwrap();
let expected = vec![DeployedPackage::Contract(DeployedContract {
id: ContractId::from_str(
"5c51b8904c539700852c646c6700fddab4b80477f66e56fb2515736facd84e69",
"02a7e78ef0514b80ab56b409f06f895d8939640b6f6d746fcbb15d3e0c6a1a3b",
)
.unwrap(),
proxy: None,
Expand Down Expand Up @@ -416,7 +416,7 @@ async fn test_deploy_submit_only() {
node.kill().unwrap();
let expected = vec![DeployedPackage::Contract(DeployedContract {
id: ContractId::from_str(
"5c51b8904c539700852c646c6700fddab4b80477f66e56fb2515736facd84e69",
"02a7e78ef0514b80ab56b409f06f895d8939640b6f6d746fcbb15d3e0c6a1a3b",
)
.unwrap(),
proxy: None,
Expand Down Expand Up @@ -462,12 +462,12 @@ async fn test_deploy_fresh_proxy() {
node.kill().unwrap();
let impl_contract = DeployedPackage::Contract(DeployedContract {
id: ContractId::from_str(
"5c51b8904c539700852c646c6700fddab4b80477f66e56fb2515736facd84e69",
"02a7e78ef0514b80ab56b409f06f895d8939640b6f6d746fcbb15d3e0c6a1a3b",
)
.unwrap(),
proxy: Some(
ContractId::from_str(
"7a78517c2c3322028db65e54893dc97958fa3d7c846a66f5675859e64f927540",
"6eb0db0e120222a4ac3ced8dfbf15ae56753b852aa7989849fa20e5aca47af44",
)
.unwrap(),
),
Expand Down
286 changes: 169 additions & 117 deletions sway-core/src/asm_generation/fuel/optimizations.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -62,82 +62,82 @@
{
"concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903",
"name": "BOOL",
"offset": 7120
"offset": 7048
},
{
"concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b",
"name": "U8",
"offset": 7312
"offset": 7240
},
{
"concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b",
"name": "ANOTHER_U8",
"offset": 7048
"offset": 6976
},
{
"concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef",
"name": "U16",
"offset": 7256
"offset": 7184
},
{
"concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc",
"name": "U32",
"offset": 7296
"offset": 7224
},
{
"concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc",
"name": "U64",
"offset": 7304
"offset": 7232
},
{
"concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e",
"name": "U256",
"offset": 7264
"offset": 7192
},
{
"concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b",
"name": "B256",
"offset": 7088
"offset": 7016
},
{
"concreteTypeId": "81fc10c4681a3271cf2d66b2ec6fbc8ed007a442652930844fcf11818c295bff",
"name": "CONFIGURABLE_STRUCT",
"offset": 7208
"offset": 7136
},
{
"concreteTypeId": "a2922861f03be8a650595dd76455b95383a61b46dd418f02607fa2e00dc39d5c",
"name": "CONFIGURABLE_ENUM_A",
"offset": 7128
"offset": 7056
},
{
"concreteTypeId": "a2922861f03be8a650595dd76455b95383a61b46dd418f02607fa2e00dc39d5c",
"name": "CONFIGURABLE_ENUM_B",
"offset": 7168
"offset": 7096
},
{
"concreteTypeId": "4926d35d1a5157936b0a29bc126b8aace6d911209a5c130e9b716b0c73643ea6",
"name": "ARRAY_BOOL",
"offset": 7056
"offset": 6984
},
{
"concreteTypeId": "776fb5a3824169d6736138565fdc20aad684d9111266a5ff6d5c675280b7e199",
"name": "ARRAY_U64",
"offset": 7064
"offset": 6992
},
{
"concreteTypeId": "c998ca9a5f221fe7b5c66ae70c8a9562b86d964408b00d17f883c906bc1fe4be",
"name": "TUPLE_BOOL_U64",
"offset": 7240
"offset": 7168
},
{
"concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a",
"name": "STR_4",
"offset": 7232
"offset": 7160
},
{
"concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b",
"name": "NOT_USED",
"offset": 7224
"offset": 7152
}
],
"encodingVersion": "1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
cmds = ["forc build --path {root} --release --ir final"]
cmds = ["forc build --path {root} --release --ir final --asm final"]
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
---
source: test/tests/tests.rs
assertion_line: 115
snapshot_kind: text
---
> forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode --release --ir final
> forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode --release --ir final --asm final
exit status: 0
output:
Building test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode
Expand Down Expand Up @@ -362,4 +361,194 @@ script {
!128 = fn_call_path_span !0 235 236
!129 = (!127 !128)

Finished release [optimized + fuel] target(s) [760 B] in ???
;; ASM: Final program
;; Program kind: Script
.program:
move $$tmp $pc
jmpf $zero i4
DATA_SECTION_OFFSET[0..32]
DATA_SECTION_OFFSET[32..64]
CONFIGURABLES_OFFSET[0..32]
CONFIGURABLES_OFFSET[32..64]
lw $$ds $$tmp i1
add $$ds $$ds $$tmp
cfei i16 ; allocate stack space for globals
addr $$arg0 data_Configurable_0; get pointer to configurable TUPLE default value
addi $$arg1 $zero i8 ; get length of configurable TUPLE default value
addi $$arg2 $ssp i0 ; get pointer to configurable TUPLE stack address
sub $$reta $pc $is ; get current instruction offset from instructions start ($is)
srli $$reta $$reta i2 ; get current instruction offset in 32-bit words
addi $$reta $$reta i4 ; set new return address
jmpf $zero i93 ; decode configurable TUPLE
addr $$arg0 data_Configurable_1; get pointer to configurable WRAPPED default value
addi $$arg1 $zero i8 ; get length of configurable WRAPPED default value
addi $$arg2 $ssp i8 ; get pointer to configurable WRAPPED stack address
sub $$reta $pc $is ; get current instruction offset from instructions start ($is)
srli $$reta $$reta i2 ; get current instruction offset in 32-bit words
addi $$reta $$reta i4 ; set new return address
jmpf $zero i85 ; decode configurable WRAPPED
move $$locbase $sp ; save locals base register for function __entry
cfei i360 ; allocate 360 bytes for locals and 0 slots for call arguments
addi $r6 $$locbase i320 ; get offset to local
sub $$reta $pc $is ; get current instruction offset from instructions start ($is)
srli $$reta $$reta i2 ; get current instruction offset in 32-bit words
addi $$reta $$reta i4 ; [call]: set new return address
jmpf $zero i140 ; [call]: call main_8
move $r0 $$retv ; [call]: copy the return value
movi $r1 i1024 ; initialize constant into register
aloc $r1
move $r1 $hp ; return value from ASM block with return register hp
addi $r2 $$locbase i112 ; get offset to local
sw $$locbase $r1 i14 ; store word
movi $r1 i1024 ; initialize constant into register
sw $$locbase $r1 i15 ; store word
sw $$locbase $zero i16 ; store word
movi $r1 i24 ; get data length for memory copy
mcp $$locbase $r2 $r1 ; copy memory
addi $r1 $$locbase i184 ; get offset to local
movi $r2 i24 ; get data length for memory copy
mcp $r1 $$locbase $r2 ; copy memory
addi $r2 $$locbase i272 ; get offset to local
movi $r3 i24 ; get data length for memory copy
mcp $r2 $r1 $r3 ; copy memory
addi $r1 $$locbase i24 ; get offset to local
movi $r3 i24 ; get data length for memory copy
mcp $r1 $r2 $r3 ; copy memory
addi $r2 $$locbase i136 ; get offset to local
movi $r3 i24 ; get data length for memory copy
mcp $r2 $r1 $r3 ; copy memory
lw $r5 $$locbase i17 ; load word
lw $r4 $$locbase i18 ; load word
lw $r1 $$locbase i19 ; load word
movi $r2 i8 ; initialize constant into register
add $r2 $r1 $r2
gt $r3 $r2 $r4
jnzf $r3 $zero i1
jmpf $zero i7
movi $r3 i2 ; initialize constant into register
mul $r3 $r4 $r3
movi $r4 i8 ; initialize constant into register
add $r4 $r3 $r4
aloc $r4
mcp $hp $r5 $r1
move $r5 $hp ; return value from ASM block with return register hp
add $r1 $r5 $r1
sw $r1 $r0 i0 ; store word
addi $r0 $$locbase i208 ; get offset to local
sw $$locbase $r5 i26 ; store word
sw $$locbase $r4 i27 ; store word
sw $$locbase $r2 i28 ; store word
addi $r1 $$locbase i48 ; get offset to local
movi $r2 i24 ; get data length for memory copy
mcp $r1 $r0 $r2 ; copy memory
addi $r0 $$locbase i248 ; get offset to local
movi $r2 i24 ; get data length for memory copy
mcp $r0 $r1 $r2 ; copy memory
addi $r1 $$locbase i336 ; get offset to local
movi $r2 i24 ; get data length for memory copy
mcp $r1 $r0 $r2 ; copy memory
addi $r0 $$locbase i336 ; get offset to local
addi $r1 $$locbase i296 ; get offset to local
movi $r2 i24 ; get data length for memory copy
mcp $r1 $r0 $r2 ; copy memory
addi $r0 $$locbase i72 ; get offset to local
movi $r2 i24 ; get data length for memory copy
mcp $r0 $r1 $r2 ; copy memory
addi $r1 $$locbase i160 ; get offset to local
movi $r2 i24 ; get data length for memory copy
mcp $r1 $r0 $r2 ; copy memory
lw $r0 $$locbase i20 ; load word
addi $r1 $r1 i16 ; get offset to aggregate element
addi $r2 $$locbase i232 ; get offset to local
sw $$locbase $r0 i29 ; store word
addi $r0 $r2 i8 ; get offset to aggregate element
movi $r3 i8 ; get data length for memory copy
mcp $r0 $r1 $r3 ; copy memory
addi $r0 $$locbase i96 ; get offset to local
movi $r1 i16 ; get data length for memory copy
mcp $r0 $r2 $r1 ; copy memory
movi $r1 i16 ; get data length for memory copy
mcp $r6 $r0 $r1 ; copy memory
lw $r0 $r6 i1 ; load size of returned slice
lw $r6 $r6 i0 ; load pointer to returned slice
retd $r6 $r0
pshl i15 ; save registers 16..40
pshh i524288 ; save registers 40..64
move $$locbase $sp ; save locals base register for function abi_decode_in_place_0
cfei i24 ; allocate 24 bytes for locals and 0 slots for call arguments
move $r0 $$arg0 ; save argument 0 (ptr)
move $r1 $$arg1 ; save argument 1 (len)
move $r2 $$arg2 ; save argument 2 (target)
move $r3 $$reta ; save return address
move $$arg0 $r0 ; [call]: pass argument 0
move $$arg1 $r1 ; [call]: pass argument 1
move $$arg2 $$locbase ; [call]: pass argument 2
sub $$reta $pc $is ; get current instruction offset from instructions start ($is)
srli $$reta $$reta i2 ; get current instruction offset in 32-bit words
addi $$reta $$reta i4 ; [call]: set new return address
jmpf $zero i19 ; [call]: call from_parts_1
lw $r0 $$retv i0 ; load word
sw $$locbase $r0 i1 ; store word
addi $r0 $$locbase i8 ; get offset to local
move $$arg0 $r0 ; [call]: pass argument 0
sub $$reta $pc $is ; get current instruction offset from instructions start ($is)
srli $$reta $$reta i2 ; get current instruction offset in 32-bit words
addi $$reta $$reta i4 ; [call]: set new return address
jmpf $zero i23 ; [call]: call abi_decode_3
move $r0 $$retv ; [call]: copy the return value
sw $$locbase $r0 i2 ; store word
addi $r0 $$locbase i16 ; get offset to local
movi $r1 i8 ; initialize constant into register
mcp $r2 $r0 $r1 ; mcp target temp size
move $$retv $zero ; set return value
cfsi i24 ; free 24 bytes for locals and 0 slots for extra call arguments
move $$reta $r3 ; restore return address
poph i524288 ; restore registers 40..64
popl i15 ; restore registers 16..40
jmp $$reta ; return from call
pshl i7 ; save registers 16..40
pshh i524288 ; save registers 40..64
move $$locbase $sp ; save locals base register for function from_parts_1
move $r0 $$arg0 ; save argument 0 (ptr)
move $r1 $$arg2 ; save argument 2 (__ret_value)
move $r2 $$reta ; save return address
sw $r1 $r0 i0 ; store word
move $$retv $r1 ; set return value
move $$reta $r2 ; restore return address
poph i524288 ; restore registers 40..64
popl i7 ; restore registers 16..40
jmp $$reta ; return from call
pshl i31 ; save registers 16..40
pshh i524288 ; save registers 40..64
move $$locbase $sp ; save locals base register for function abi_decode_3
move $r0 $$arg0 ; save argument 0 (buffer)
move $r1 $$reta ; save return address
lw $r2 $r0 i0 ; load word
lw $r2 $r2 i0 ; lw val ptr i0
lw $r3 $r0 i0 ; load word
movi $r4 i8 ; initialize constant into register
add $r3 $r3 $r4
sw $r0 $r3 i0 ; store word
move $$retv $r2 ; set return value
move $$reta $r1 ; restore return address
poph i524288 ; restore registers 40..64
popl i31 ; restore registers 16..40
jmp $$reta ; return from call
pshl i7 ; save registers 16..40
pshh i524288 ; save registers 40..64
move $$locbase $sp ; save locals base register for function main_8
move $r2 $$reta ; save return address
lw $r0 $ssp i1 ; load word
lw $r1 $ssp i0 ; load word
add $r0 $r0 $r1
move $$retv $r0 ; set return value
move $$reta $r2 ; restore return address
poph i524288 ; restore registers 40..64
popl i7 ; restore registers 16..40
jmp $$reta ; return from call
.data:
data_<Configurable, TUPLE>_0 .bytes[8] 00 00 00 00 00 00 00 02 ........
data_<Configurable, WRAPPED>_1 .bytes[8] 00 00 00 00 00 00 00 01 ........


Finished release [optimized + fuel] target(s) [752 B] in ???
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::hash::*;
#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x14ed3cd06c2947248f69d54bfa681fe40d26267be84df7e19e253622b7921bbe;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x6b01f04c84ce955e8dfc6ed3611fd2518424ab757e5a540878f49fbd1bdec571; // AUTO-CONTRACT-ID ../../test_contracts/array_of_structs_contract --release
const CONTRACT_ID = 0xe0c85555f3d94e58cc23830deb6dc193e1f173761a4fc5d56d3e07a5a1db0378; // AUTO-CONTRACT-ID ../../test_contracts/array_of_structs_contract --release

fn get_address() -> Option<std::address::Address> {
Some(CONTRACT_ID.into())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use test_fuel_coin_abi::*;
#[cfg(experimental_new_encoding = false)]
const FUEL_COIN_CONTRACT_ID = 0xec2277ebe007ade87e3d797c3b1e070dcd542d5ef8f038b471f262ef9cebc87c;
#[cfg(experimental_new_encoding = true)]
const FUEL_COIN_CONTRACT_ID = 0x19c0d374734bd8a92b776787e9dffa0f105a90e3c977626f93a1916de54dd714;
const FUEL_COIN_CONTRACT_ID = 0xcdb572031a0779e09beea1e93e21630d104766c90cc8ce90c8dfd0abdd0ce5b2; // AUTO-CONTRACT-ID ../../test_contracts/test_fuel_coin_contract --release

#[cfg(experimental_new_encoding = false)]
const BALANCE_CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
category = "run_on_node"
expected_result = { action = "result", value = 1 }
expected_result_new_encoding = { action = "return_data", value = "01" }
contracts = ["should_pass/test_contracts/balance_test_contract", "should_pass/test_contracts/test_fuel_coin_contract"]
unsupported_profiles = ["debug"]
contracts = [
"should_pass/test_contracts/balance_test_contract",
"should_pass/test_contracts/test_fuel_coin_contract",
]
unsupported_profiles = ["debug"]
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use basic_storage_abi::{BasicStorage, Quad};
#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x94db39f409a31b9f2ebcadeea44378e419208c20de90f5d8e1e33dc1523754cb;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x7d78bfaba7c715105ec3ec568b8c64dbb77491d45dec52b549e59c0cf5cf5c5e; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release
const CONTRACT_ID = 0x52954afa6e6020d78b4daa89bc2bfceb31a7b85a97f55a49946f67d4e03b66c0; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release

fn main() -> u64 {
let addr = abi(BasicStorage, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use contract_with_type_aliases_abi::*;
#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x0cbeb6efe3104b460be769bdc4ea101ebf16ccc16f2d7b667ec3e1c7f5ce35b5;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x2e8efc627379d037c6ac70249d0bf0726f228ea6bade786e11639b878241f333; // AUTO-CONTRACT-ID ../../test_contracts/contract_with_type_aliases --release
const CONTRACT_ID = 0x5f2d9be937ca4a0de3404d1165d0faed6f8c440ab9ba7c6c046904e28761f7f7; // AUTO-CONTRACT-ID ../../test_contracts/contract_with_type_aliases --release

fn main() {
let caller = abi(MyContract, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::hash::*;
#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x3bc28acd66d327b8c1b9624c1fabfc07e9ffa1b5d71c2832c3bfaaf8f4b805e9;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0xb509b52a765f2a8e97b29e4699d0ec8fa056b2bb649f785c75e36f868c318b98; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release
const CONTRACT_ID = 0x03ad85f37b515247a0481ba4d1448a5592b8684312e7f2626d4403ab9fec2acc; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release

fn main() -> bool {
let caller = abi(StorageAccess, CONTRACT_ID);
Expand Down

0 comments on commit bcd15c3

Please sign in to comment.