akldc opened issue #11911:
.clifTest Casetest optimize set opt_level=none set preserve_frame_pointers=true target s390x target aarch64 target riscv64 target x86_64 function %main() -> i8x16, i8x16, i8x16, i32, i8x16, i8x16 tail { const0 = 0x00000000000000000000000000000000 const1 = 0x7ecbb59efd61c837c76c86aef296bb9f block0: v8 = vconst.i8x16 const0 v9 = vconst.i8x16 const1 v10 = bnot v9 ; v9 = const1 v11 = bitcast.f64x2 little v10 v12 = sqrt v11 v13 = sqrt v12 v14 = bitcast.i8x16 little v13 v15 = iconst.i32 0x3693_344b v16 = bitcast.i8x16 little v13 jump block1(v16, v14, v14, v15, v14, v14) ; v15 = 0x3693_344b block1(v2: i8x16, v3: i8x16, v4: i8x16, v5: i32, v6: i8x16, v7: i8x16): return v2, v3, v4, v5, v6, v7 } ; print: %main()Description
The execution results of the above Cranelift code differ between x86_64 and aarch64.
[x86 ] %main() -> [0xfff80000000000003e17c443ecb03841, 0xfff80000000000003e17c443ecb03841, 0xfff80000000000003e17c443ecb03841, 915616843, 0xfff80000000000003e17c443ecb03841, 0xfff80000000000003e17c443ecb03841] [aarch64] %main() -> [0x7ff80000000000003e17c443ecb03841, 0x7ff80000000000003e17c443ecb03841, 0x7ff80000000000003e17c443ecb03841, 915616843, 0x7ff80000000000003e17c443ecb03841, 0x7ff80000000000003e17c443ecb03841]To verify if the architecture-specific discrepancy stems from Cranelift's handling, I lifted the original
.clifcode to its equivalent WebAssembly module.(module (type (;0;) (func (result v128 v128 v128 i32 v128 v128))) (func (;0;) (type 0) (result v128 v128 v128 i32 v128 v128) (local v128) v128.const i32x4 0xf296bb9f 0xc76c86ae 0xfd61c837 0x7ecbb59e v128.not f64x2.sqrt f64x2.sqrt local.tee 0 local.get 0 local.get 0 i32.const 915616843 local.get 0 local.get 0) (export "main" (func 0)))The Wasm module shows similar architecture differences.
x86_64 result:340240828546070184846820624011963152449 340240828546070184846820624011963152449 340240828546070184846820624011963152449 915616843 340240828546070184846820624011963152449 340240828546070184846820624011963152449aarch64 result:
170099645085600953115133320296079046721 170099645085600953115133320296079046721 170099645085600953115133320296079046721 915616843 170099645085600953115133320296079046721 170099645085600953115133320296079046721This is just like the ordinary Wasm programs we usually encounter, and the same code should produce consistent results across different architectures.
akldc added the bug label to Issue #11911.
akldc added the cranelift label to Issue #11911.
bjorn3 commented on issue #11911:
Wasm doesn't specify the NaN payload that is used for float operations that produce a NaN for performance reasons as architectures disagree about when they preserve the input NaN vs when they create a new NaN with a payload specified by the architecture. You can set the
enable_nan_canonicalizationCranelift flag if you absolutely need consistent NaN payloads across architectures and don't care about the perf hit.
alexcrichton closed issue #11911:
.clifTest Casetest optimize set opt_level=none set preserve_frame_pointers=true target s390x target aarch64 target riscv64 target x86_64 function %main() -> i8x16, i8x16, i8x16, i32, i8x16, i8x16 tail { const0 = 0x00000000000000000000000000000000 const1 = 0x7ecbb59efd61c837c76c86aef296bb9f block0: v8 = vconst.i8x16 const0 v9 = vconst.i8x16 const1 v10 = bnot v9 ; v9 = const1 v11 = bitcast.f64x2 little v10 v12 = sqrt v11 v13 = sqrt v12 v14 = bitcast.i8x16 little v13 v15 = iconst.i32 0x3693_344b v16 = bitcast.i8x16 little v13 jump block1(v16, v14, v14, v15, v14, v14) ; v15 = 0x3693_344b block1(v2: i8x16, v3: i8x16, v4: i8x16, v5: i32, v6: i8x16, v7: i8x16): return v2, v3, v4, v5, v6, v7 } ; print: %main()Description
The execution results of the above Cranelift code differ between x86_64 and aarch64.
[x86 ] %main() -> [0xfff80000000000003e17c443ecb03841, 0xfff80000000000003e17c443ecb03841, 0xfff80000000000003e17c443ecb03841, 915616843, 0xfff80000000000003e17c443ecb03841, 0xfff80000000000003e17c443ecb03841] [aarch64] %main() -> [0x7ff80000000000003e17c443ecb03841, 0x7ff80000000000003e17c443ecb03841, 0x7ff80000000000003e17c443ecb03841, 915616843, 0x7ff80000000000003e17c443ecb03841, 0x7ff80000000000003e17c443ecb03841]To verify if the architecture-specific discrepancy stems from Cranelift's handling, I lifted the original
.clifcode to its equivalent WebAssembly module.(module (type (;0;) (func (result v128 v128 v128 i32 v128 v128))) (func (;0;) (type 0) (result v128 v128 v128 i32 v128 v128) (local v128) v128.const i32x4 0xf296bb9f 0xc76c86ae 0xfd61c837 0x7ecbb59e v128.not f64x2.sqrt f64x2.sqrt local.tee 0 local.get 0 local.get 0 i32.const 915616843 local.get 0 local.get 0) (export "main" (func 0)))The Wasm module shows similar architecture differences.
x86_64 result:340240828546070184846820624011963152449 340240828546070184846820624011963152449 340240828546070184846820624011963152449 915616843 340240828546070184846820624011963152449 340240828546070184846820624011963152449aarch64 result:
170099645085600953115133320296079046721 170099645085600953115133320296079046721 170099645085600953115133320296079046721 915616843 170099645085600953115133320296079046721 170099645085600953115133320296079046721This is just like the ordinary Wasm programs we usually encounter, and the same code should produce consistent results across different architectures.
alexcrichton commented on issue #11911:
Agreed yes, this is NaN issues which is expected for Cranelift to have diverging results on different platforms with. There's some brief information on the topic here and in addition to the Cranelift setting
enable_nan_canonicalizationyou can also for wasm set the-Wnan-canonicalizationflag which makes the wasm behave the same across architectures.
Last updated: Dec 06 2025 at 06:05 UTC