bytecodealliance / wasm-tools

CLI and Rust libraries for low-level manipulation of WebAssembly modules
Apache License 2.0
1.21k stars 224 forks source link

shrink: Ineffective on non-tree-like expressions (?) #1633

Open alexcrichton opened 1 week ago

alexcrichton commented 1 week ago

I'm not sure why wasm-tools shrink is ineffective here but I wanted to write this down with reproduction instructions before I forgot.

Given this input

foo.wat ```wasm (module (type (;0;) (func (param f64 f64 f64 f64) (result f32 f64))) (func (;0;) (type 0) (param f64 f64 f64 f64) (result f32 f64) (local f64 f64 f64 f64 f64 f64 f64 f64 f64 f32 f64 f32 f32 f32 i32 i32 f32 f32 f64 f64 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32) global.get 8 if ;; label = @1 unreachable end global.get 8 global.set 8 f64.const 0x1.fffffffffffffp+0 (;=1.9999999999999998;) local.get 4 i64.const 0 f64.const nan (;=NaN;) i64.const 0 local.get 0 f64.const 0x1.8285b20746e23p-381 (;=0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030655343237919207;) i64.const -4850376798678024192 i32.const 0 i64.const 0 f32.const 0x1.a2db4ap+58 (;=471590600000000000;) local.get 1 i32.const 0 br_if 0 i32.const 1 i64.const 0 global.get 1 f32.const -0x1.1076bp+48 (;=-299576920000000;) local.get 1 i32.const 0 if (result f32) ;; label = @1 global.get 1 i64.const 0 local.get 1 i64.const 0 i64.extend32_s i32.const 1 if (result f32) ;; label = @2 f64.const 0x1.fffffffffffffp+0 (;=1.9999999999999998;) i32.const 0 i32.const -1079430155 i32.or if ;; label = @3 end i32.const 0 if ;; label = @3 end i32.const 1 if ;; label = @3 end i32.const 1 i64.const 0 global.get 1 block ;; label = @3 loop (result i32) ;; label = @4 global.get 8 if ;; label = @5 unreachable end global.get 8 global.set 8 global.get 1 br 1 (;@3;) local.set 0 br 0 (;@4;) br 0 (;@4;) br 1 (;@3;) br 0 (;@4;) br 0 (;@4;) global.get 3 local.get 15 br 0 (;@4;) local.tee 17 local.get 17 f32.ne i32.const 0 i32.or if ;; label = @5 end local.get 17 f32.const -0x1.fffffep+30 (;=-2147483500;) f32.lt if ;; label = @5 nop end i32.const 1 if ;; label = @5 end local.set 19 block ;; label = @5 block ;; label = @6 local.get 19 br_if 0 (;@6;) i32.const 1 br_if 0 (;@6;) br 1 (;@5;) end end local.get 18 block ;; label = @5 i32.const 1 i64.const 1 local.get 2 i32.const 1 i32.const 0 i32.const 0 local.get 23 br 1 (;@4;) i32.const 0 i32.const 0 if (result f32) ;; label = @6 f64.const 0x1.7c6572cfc0c5ap+420 (;=4023411735552251000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;) i32.const -16384 i32.const 0 i32.const 0 global.get 3 i32.eqz global.get 2 f32.const -nan:0x7fc000 (;=NaN;) f32.const -nan:0x7fc000 (;=NaN;) f32.const -0x1p+1 (;=-2;) f32.const -nan:0x7e0000 (;=NaN;) br 1 (;@5;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const -nan:0x7e0000 (;=NaN;) local.get 1 i32.const 1353088863 br_if 1 (;@5;) block ;; label = @7 local.get 24 f32.const -nan:0x7fc000 (;=NaN;) f32.const -nan:0x7fc000 (;=NaN;) f32.const -0x1p+1 (;=-2;) f32.const -nan:0x7e0000 (;=NaN;) br 5 (;@2;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const -nan:0x7e0000 (;=NaN;) local.get 1 i32.const 0 i32.const 0 i32.const 0 i64.const 0 i32.const 1 if (result f32) ;; label = @8 i32.const 0 i64.const 0 br 3 (;@5;) i64.popcnt f64.convert_i64_u f64.neg i32.trunc_sat_f64_u f64.const -0x1.9697261760a3bp+928 (;=-3603737573424275000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;) br 3 (;@5;) i32.const 0 i32.extend8_s br 3 (;@5;) i64.const 0 br 5 (;@3;) loop (result f64) ;; label = @9 global.get 8 if ;; label = @10 unreachable end i32.const 0 global.set 8 f32.const 0x1.c2dcbap+89 (;=1090117940000000000000000000;) block ;; label = @10 i64.const 1 br 5 (;@5;) global.get 0 br 3 (;@7;) local.get 1 br 6 (;@4;) global.set 0 f64.abs f64.abs f64.abs global.set 1 br 6 (;@4;) local.get 29 i64.const 0 local.get 30 i64.const 0 i32.const 0 loop (result f32) ;; label = @11 global.get 8 if ;; label = @12 unreachable end i32.const 0 global.set 8 i32.const 1 if ;; label = @12 end f32.const -0x1.4b8638p-52 (;=-0.00000000000000028755149;) end i64.trunc_sat_f32_s i64.const 0 i64.le_u i32.gt_s i64.extend_i32_u i64.mul i64.const 0 i64.mul i32.const 0 local.get 3 br 0 (;@10;) i64.trunc_sat_f64_u i64.ctz loop (result i32) ;; label = @11 global.get 8 if ;; label = @12 unreachable end global.get 8 global.set 8 block ;; label = @12 i64.const 0 br 9 (;@3;) i64.const 0 i64.lt_u i32.ctz i32.clz i32.clz br_if 8 (;@4;) br 9 (;@3;) i64.const 1 br 0 (;@12;) i64.popcnt f32.const 0x1.2aa6fap-55 (;=0.000000000000000032379942;) br 10 (;@2;) f64.const -0x1.eae540f9093d5p-883 (;=-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029734657088404895;) br 2 (;@10;) global.set 1 br 0 (;@12;) i64.popcnt i64.popcnt i64.popcnt i64.popcnt i64.popcnt i64.eqz i64.const 0 local.get 36 i64.const 1 f32.const 0x0p+0 (;=0;) i64.const 0 f32.const 0x1.7dcadep-122 (;=0.0000000000000000000000000000000000002804968;) i32.const 1 i32.const -809609695 i32.const 0 global.get 1 i32.const 0 br 7 (;@5;) i32.const 25 i32.lt_s i32.eqz i32.eqz i32.eqz i32.eqz i32.eqz i32.eqz i32.eqz i32.eqz i32.eqz br_if 0 (;@12;) block ;; label = @13 local.get 43 f32.const -nan:0x7fc000 (;=NaN;) f32.const -0x1.28f106p-43 (;=-0.00000000000013186852;) f32.const -0x1p+1 (;=-2;) f32.const -nan:0x7e0000 (;=NaN;) br 9 (;@4;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const 0x1p-95 (;=0.00000000000000000000000000002524355;) f32.const -nan:0x7e0000 (;=NaN;) local.get 1 i32.const 0 i32.const 0 i32.const 0 i64.const 1 i32.const 0 if (result f32) ;; label = @14 i32.const 0 i64.const 1 br 1 (;@13;) i64.popcnt f64.convert_i64_u f64.neg i32.trunc_sat_f64_u f64.const -0x1.9697261760a3bp+928 (;=-3603737573424275000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;) br 9 (;@5;) i32.const 0 br 3 (;@11;) i64.const 1 br 10 (;@4;) loop (result f64) ;; label = @15 global.get 8 if ;; label = @16 unreachable end global.get 8 global.set 8 f32.const 0x1.c2dcbap+89 (;=1090117940000000000000000000;) block ;; label = @16 i64.const 0 br 9 (;@7;) global.get 0 br 13 (;@3;) local.get 1 br 13 (;@3;) global.set 0 f64.abs f64.abs f64.abs global.set 1 br 13 (;@3;) local.get 47 i64.const 0 local.get 49 i64.const 0 i32.const 0 loop (result f32) ;; label = @17 global.get 8 if ;; label = @18 unreachable end global.get 8 global.set 8 i32.const 0 if ;; label = @18 end i64.const 0 f32.convert_i64_u end i64.trunc_sat_f32_s i64.const 1 i64.le_u i32.gt_s i64.extend_i32_u i64.mul i64.const 1 i64.mul i32.const 1 block ;; label = @17 block ;; label = @18 global.get 8 if ;; label = @19 unreachable end i32.const 1 global.set 8 br 1 (;@17;) end block ;; label = @18 block ;; label = @19 global.get 8 if ;; label = @20 unreachable end i32.const 0 global.set 8 br 1 (;@18;) end block ;; label = @19 block ;; label = @20 global.get 8 if ;; label = @21 else unreachable end i32.const 0 global.set 8 br 1 (;@19;) end loop ;; label = @20 global.get 8 if ;; label = @21 else unreachable end i32.const 0 global.set 8 end end end end global.get 4 i32.xor global.set 4 global.get 5 i64.xor global.set 5 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 end i32.reinterpret_f32 i32.const 0 i32.xor global.set 6 f64.const 0x1.e6c616e67786cp+803 (;=101431707399954290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;) end i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 4 i32.xor global.set 4 i32.const 1 i32.xor global.set 4 f32.const 0x1.ap-145 (;=0.000000000000000000000000000000000000000000036;) else f32.const 0x1.5cc6fp+103 (;=13816484000000000000000000000000;) end i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 i64.reinterpret_f64 i64.const 0 i64.xor global.set 7 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 i32.const 0 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 end i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 end i32.const 0 end global.get 4 i32.xor global.set 4 global.get 5 i64.xor global.set 5 i32.const 0 i32.xor global.set 4 global.get 5 i64.xor global.set 5 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 end i32.reinterpret_f32 global.get 6 i32.xor global.set 6 f64.const 0x1.10a20310a2031p-508 (;=0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001270867974337706;) end i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 4 i32.xor global.set 4 i32.const 0 i32.xor global.set 4 f32.const 0x1.p-135 (;=0.000000000000000000000000000000000000000022959;) else f32.const 0x1.144062p-29 (;=0.0000000020099942;) end i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 end i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 i32.const 1 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 f32.const 0x1.0c1ccp+0 (;=1.0473137;) else f32.const 0x1.406214p-107 (;=0.000000000000000000000000000000007712943;) end i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i32.const 0 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 4 i32.xor global.set 4 global.get 4 i32.xor global.set 4 i32.const 1 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 end end global.get 4 i32.xor global.set 4 end i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 f32.const 0x1.p-135 (;=0.000000000000000000000000000000000000000022959;) else f32.const 0x1.144062p-29 (;=0.0000000020099942;) end i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i64.const 0 i64.xor global.set 5 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 f32.const 0x1.p-135 (;=0.000000000000000000000000000000000000000022959;) else f32.const 0x1.144062p-29 (;=0.0000000020099942;) end i32.reinterpret_f32 i32.const 0 i32.xor global.set 6 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i32.reinterpret_f32 global.get 6 i32.xor global.set 6 global.get 5 i64.xor global.set 5 global.get 4 i32.xor global.set 4 global.get 5 i64.xor global.set 5 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i64.const 0 i64.xor global.set 5 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 global.get 5 i64.xor global.set 5 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 i64.reinterpret_f64 global.get 7 i64.xor global.set 7 f32.const 0x1.p-135 (;=0.000000000000000000000000000000000000000022959;) f64.const 0x1.10a20310a2031p-508 (;=0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001270867974337706;) ) (global (;0;) (mut f64) f64.const -0x1.9898989898989p-875 (;=-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006335895749884723;)) (global (;1;) (mut f64) f64.const -0x1.9898989898989p-876 (;=-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031679478749423613;)) (global (;2;) (mut f32) f32.const 0x0p+0 (;=0;)) (global (;3;) i32 i32.const 0) (global (;4;) (mut i32) i32.const 0) (global (;5;) (mut i64) i64.const 0) (global (;6;) (mut i32) i32.const 0) (global (;7;) (mut i64) i64.const 0) (global (;8;) (mut i32) i32.const 0) ) ```

and this script:

#!/bin/sh

$HOME/code/wasmtime/target/debug/wasmtime \
  compile -C compiler=winch -o /dev/null \
  --target x86_64 \
  $1 2>&1 | grep panic

and using Wasmtime at bytecodealliance/wasmtime@7112d93b481c4baa366c7e56d6cd5b8e68805cea (make sure to build Wasmtime with debug assertions on)

then this invocation:

$ cargo run --release shrink ./test.sh ./foo.wat

Is not effectively shrinking the module any further. A fully shrunk module should look something like https://github.com/bytecodealliance/wasmtime/issues/8848 but the main function body here is significantly larger than it is in the issue. I tried to figure out why wasm-mutate wasn't performing expected mutations here but I couldn't figure it out. It seemed like it might be related to "Basic block cannot be constructed for opcode" but I didn't dig too too far as I don't understand wasm-mutate well enough.