scalar_replacement.js (4631B)
1 // Scalar Replacement of wasm structures. 2 3 // A very simple example, this struct should be replaced. 4 var code =` 5 (module 6 (type $point (struct 7 (field $x i32) 8 (field $y i32) 9 )) 10 11 (func $test (result i32) 12 i32.const 42 13 i32.const 11 14 struct.new $point 15 struct.get $point 1 16 return 17 ) 18 )`; 19 20 let module = new WebAssembly.Module(wasmTextToBinary(code)); 21 instance = new WebAssembly.Instance(module); 22 23 // This struct contains a lot of fields and should not be optimized. 24 code =` 25 (module 26 (type $point (struct 27 (field $x i32) 28 (field $y1 i32) 29 (field $x2 i32) 30 (field $y3 i32) 31 (field $x4 i32) 32 (field $y5 i32) 33 (field $x6 i32) 34 (field $y7 i32) 35 (field $x8 i32) 36 (field $y9 i32) 37 (field $x10 i32) 38 (field $y11 i32) 39 (field $x12 i32) 40 (field $y13 i32) 41 (field $x14 i32) 42 (field $y15 i32) 43 )) 44 45 (func $test (result i32) 46 i32.const 42 47 i32.const 42 48 i32.const 42 49 i32.const 42 50 i32.const 42 51 i32.const 42 52 i32.const 42 53 i32.const 42 54 i32.const 42 55 i32.const 42 56 i32.const 42 57 i32.const 42 58 i32.const 42 59 i32.const 42 60 i32.const 42 61 i32.const 42 62 struct.new $point 63 struct.get $point 10 64 return 65 ) 66 )`; 67 68 module = new WebAssembly.Module(wasmTextToBinary(code)); 69 70 // Using parameters instead of constants to create the struct. 71 code =` 72 (module 73 (type $point (struct 74 (field $x i32) 75 (field $y i32) 76 )) 77 78 (func $test (param i32) (param i32) (result i32) 79 local.get 0 80 local.get 1 81 struct.new $point 82 struct.get $point 1 83 return 84 ) 85 )`; 86 87 module = new WebAssembly.Module(wasmTextToBinary(code)); 88 instance = new WebAssembly.Instance(module); 89 90 91 // Filling the struct with if/then/else structure around it. 92 code =` 93 (module 94 (type $point (struct 95 (field $x (mut i32)) 96 (field $y (mut i32)) 97 )) 98 99 (func $createAndReturnField (param $cond i32) (result i32) 100 (local $s (ref null $point)) 101 102 ;; Initialize the struct with some constants 103 (struct.new $point (i32.const 12) (i32.const 13)) 104 (local.set $s) 105 106 (local.get $cond) 107 (if (then 108 (struct.set $point $x (local.get $s) (i32.const 10)) 109 (struct.set $point $y (local.get $s) (i32.const 20)) 110 ) (else 111 (struct.set $point $x (local.get $s) (i32.const 30)) 112 (struct.set $point $y (local.get $s) (i32.const 40)) 113 )) 114 115 (struct.get $point $x (local.get $s)) 116 ) 117 )`; 118 119 module = new WebAssembly.Module(wasmTextToBinary(code)); 120 instance = new WebAssembly.Instance(module); 121 122 123 // Same test but with a struct escaping in one of the branches. 124 // This should prevent the struct to be optimized. 125 code =` 126 (module 127 (type $point (struct 128 (field $x (mut i32)) 129 (field $y (mut i32)) 130 )) 131 132 (global $escapedPoint (mut (ref null $point)) (ref.null $point)) 133 134 (func $createAndReturnField (param $cond i32) (result i32) 135 (local $s (ref null $point)) 136 137 ;; Initialize the struct with some constants 138 (struct.new $point (i32.const 12) (i32.const 13)) 139 (local.set $s) 140 141 (local.get $cond) 142 (if (then 143 (struct.set $point $x (local.get $s) (i32.const 10)) 144 (struct.set $point $y (local.get $s) (i32.const 20)) 145 ;; Storing this struct in a global 146 (global.set $escapedPoint (local.get $s)) 147 ) (else 148 (struct.set $point $x (local.get $s) (i32.const 30)) 149 (struct.set $point $y (local.get $s) (i32.const 40)) 150 )) 151 152 (struct.get $point $x (local.get $s)) 153 ) 154 )`; 155 156 module = new WebAssembly.Module(wasmTextToBinary(code)); 157 instance = new WebAssembly.Instance(module); 158 159 // In this example, one struct is stored into another one. 160 // The inner struct is escaping into the other one and will 161 // not be optimized. 162 // The outer struct will be optimized by Scalar Replacement. 163 code =` 164 (module 165 ;; Define a struct type for the inner struct 166 (type $InnerStruct (struct 167 (field (mut i32)) 168 )) 169 170 ;; Define a struct type for the outer struct 171 (type $OuterStruct (struct 172 (field (mut i32)) 173 (field (mut i32)) 174 (field (ref $InnerStruct)) ;; Reference to InnerStruct 175 )) 176 177 ;; Define a function to create and fill both structs. 178 (func $createStructs (result (ref $InnerStruct)) 179 (local $inner (ref $InnerStruct)) 180 (local $outer (ref $OuterStruct)) 181 182 i32.const 42 183 struct.new $InnerStruct 184 local.set $inner 185 186 i32.const 10 187 i32.const 20 188 local.get $inner 189 struct.new $OuterStruct 190 local.set $outer 191 192 ;; Return the inner struct 193 local.get $outer 194 struct.get $OuterStruct 2 195 ) 196 )`; 197 198 module = new WebAssembly.Module(wasmTextToBinary(code)); 199 instance = new WebAssembly.Instance(module);