cmp-bitselect.js (5022B)
1 // |jit-test| skip-if: !wasmSimdEnabled() 2 // Tests if combination of comparsion and bitselect produces correct result. 3 // On x86/64 platforms, it is expected to replace slow bitselect emulation, 4 // with its faster laneselect equivalent (pblendvb). 5 // See bug 1751488 for more information. 6 7 let verifyCodegen = _method => {}; 8 if (hasDisassembler() && wasmCompileMode() == "ion" && 9 getBuildConfiguration("x64") && !getBuildConfiguration("simulator")) { 10 if (isAvxPresent()) { 11 verifyCodegen = method => { 12 assertEq(wasmDis(method, {asString: true}).includes('vpblendvb'), true); 13 }; 14 } else { 15 verifyCodegen = method => { 16 assertEq(wasmDis(method, {asString: true}).includes("pblendvb"), true); 17 }; 18 } 19 } 20 21 const checkOps = { 22 eq(a, b) { return a == b; }, 23 ne(a, b) { return a != b; }, 24 lt(a, b) { return a < b; }, 25 le(a, b) { return a <= b; }, 26 gt(a, b) { return a > b; }, 27 ge(a, b) { return a >= b; }, 28 }; 29 const checkPattern = new Uint8Array(Array(32).fill(null).map((_, i) => i)); 30 31 for (let [laneSize, aty_s, aty_u] of [ 32 [8, Int8Array, Uint8Array], [16, Int16Array, Uint16Array], 33 [32, Int32Array, Uint32Array], [64, BigInt64Array, BigUint64Array]]) { 34 const laneCount = 128 / laneSize; 35 const ty = `i${laneSize}x${laneCount}`; 36 for (let op of ['eq', 'ne', 'lt_s', 'le_s', 'gt_s', 'ge_s', 'lt_u', 'le_u', 'gt_u', 'ge_u']) { 37 if (laneSize == 64 && op.includes('_u')) continue; 38 const wrap = laneSize < 64 ? x => x : x => BigInt(x); 39 const aty = op.includes('_u') ? aty_u : aty_s; 40 const check = checkOps[op.replace(/_[us]$/, "")]; 41 // Items to test: 0, 1, all 1s, top half 1s, low half 1s, top bit 1 42 const testData = new aty([wrap(0), wrap(1), ~wrap(0), ~wrap(0) << wrap(laneSize / 2), 43 ~((~wrap(0)) << wrap(laneSize / 2)), wrap(1) << wrap(laneSize - 1)]); 44 const ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module 45 (memory (export "memory") 1) 46 (func (export "run") 47 (v128.store (i32.const 32) 48 (v128.bitselect (v128.load (i32.const 64)) (v128.load (i32.const 80)) (${ty}.${op} (v128.load (i32.const 0)) (v128.load (i32.const 16))))) ))`))); 49 const mem = new aty(ins.exports.memory.buffer); 50 const memI8 = new Uint8Array(ins.exports.memory.buffer); 51 memI8.subarray(64, 96).set(checkPattern); 52 verifyCodegen(ins.exports.run); 53 for (let i = 0; i < testData.length; i++) { 54 for (let j = 0; j < testData.length; j++) { 55 for (let q = 0; q < laneCount; q++) { 56 mem[q] = testData[(i + q) % testData.length]; 57 mem[q + laneCount] = testData[(j + q) % testData.length]; 58 } 59 ins.exports.run(); 60 for (let q = 0; q < laneCount; q++) { 61 const val = check(mem[q], mem[q + laneCount]); 62 const n = laneSize >> 3; 63 for (let k = 0; k < n; k++) { 64 assertEq(checkPattern[q * n + k + (val ? 0 : 16)], 65 memI8[32 + q * n + k]); 66 } 67 } 68 } 69 } 70 } 71 } 72 73 for (let [laneSize, aty] of [[32, Float32Array], [64, Float64Array]]) { 74 const laneCount = 128 / laneSize; 75 const ty = `f${laneSize}x${laneCount}`; 76 for (let op of ['eq', 'ne', 'lt', 'le', 'gt', 'ge']) { 77 const check = checkOps[op]; 78 // Items to test: 0, 1, -1, PI, NaN, Inf, -0, -Inf 79 const testData = new aty([0, 1, -1, Math.PI, NaN, Infinity, 0/-Infinity, -Infinity]); 80 const ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module 81 (memory (export "memory") 1) 82 (func (export "run") 83 (v128.store (i32.const 32) 84 (v128.bitselect (v128.load (i32.const 64)) (v128.load (i32.const 80)) (${ty}.${op} (v128.load (i32.const 0)) (v128.load (i32.const 16))))) ))`))); 85 const mem = new aty(ins.exports.memory.buffer); 86 const memI8 = new Uint8Array(ins.exports.memory.buffer); 87 memI8.subarray(64, 96).set(checkPattern); 88 verifyCodegen(ins.exports.run); 89 for (let i = 0; i < testData.length; i++) { 90 for (let j = 0; j < testData.length; j++) { 91 for (let q = 0; q < laneCount; q++) { 92 mem[q] = testData[(i + q) % testData.length]; 93 mem[q + laneCount] = testData[(j + q) % testData.length]; 94 } 95 ins.exports.run(); 96 for (let q = 0; q < laneCount; q++) { 97 const val = check(mem[q], mem[q + laneCount]); 98 const n = laneSize >> 3; 99 for (let k = 0; k < n; k++) { 100 assertEq(checkPattern[q * n + k + (val ? 0 : 16)], 101 memI8[32 + q * n + k]); 102 } 103 } 104 } 105 } 106 } 107 }