Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| test-also=--wasm-compiler=optimizing; skip-if: !hasDisassembler() || wasmCompileMode() != "ion" || !getBuildConfiguration("loong64"); include:codegen-loong64-test.js
const NopIns = `andi \\$zero, \\$zero, 0x0`;
// Test that small i64 constants in bin-ops are folded into {AND,OR,XOR}I.
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.and (local.get 0) (i64.const 0xff))))`,
"f",
`andi \\$a0, \\$a0, 0xff`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.or (local.get 0) (i64.const 0x100))))`,
"f",
`ori \\$a0, \\$a0, 0x100`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.xor (local.get 0) (i64.const 0x1f))))`,
"f",
`xori \\$a0, \\$a0, 0x1f`);
// Test that small i32 constants in bin-ops are folded into {AND,OR,XOR}I.
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i32) (result i32)
(i32.and (local.get 0) (i32.const 0xff))))`,
"f",
`andi \\$a0, \\$a0, 0xff`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i32) (result i32)
(i32.or (local.get 0) (i32.const 0x100))))`,
"f",
`ori \\$a0, \\$a0, 0x100`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i32) (result i32)
(i32.xor (local.get 0) (i32.const 0x1f))))`,
"f",
`xori \\$a0, \\$a0, 0x1f`);
// A contiguous run of one-bits is applied with BSTRPICK.D and optional SLLI.D.
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.and (local.get 0) (i64.const 0xffffffff))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0x1f, 0x0`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.and (local.get 0) (i64.const 0x7fffffff))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0x1e, 0x0`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.and (local.get 0) (i64.const 0xff00))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0xf, 0x8
slli.d \\$a0, \\$a0, 0x8`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.and (local.get 0) (i64.const 0xffff0000))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0x1f, 0x10
slli.d \\$a0, \\$a0, 0x10`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.and (local.get 0) (i64.const 0xffffffffffffff00))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0x3f, 0x8
slli.d \\$a0, \\$a0, 0x8`);
// A contiguous run of one-bits in an i32 mask is applied with BSTRPICK.D
// followed by an optional SLLI.D.
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i32) (result i32)
(i32.and (local.get 0) (i32.const 0x7fffffff))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0x1e, 0x0`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i32) (result i32)
(i32.and (local.get 0) (i32.const 0xff00))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0xf, 0x8
slli.d \\$a0, \\$a0, 0x8`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i32) (result i32)
(i32.and (local.get 0) (i32.const 0xffff0000))))`,
"f",
`bstrpick\\.d \\$a0, \\$a0, 0x3f, 0x10
slli.d \\$a0, \\$a0, 0x10`);
// Test that signed comparisons against negative constants use SLTI directly.
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i32)
(i64.lt_s (local.get 0) (i64.const -100))))`,
"f",
`slti \\$a0, \\$a0, -100`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i32)
(i64.ge_s (local.get 0) (i64.const -100))))`,
"f",
`slti \\$a0, \\$a0, -100
xori \\$a0, \\$a0, 0x1`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i32)
(i64.gt_s (local.get 0) (i64.const -100))))`,
"f",
`slti \\$a0, \\$a0, -99
xori \\$a0, \\$a0, 0x1`);
// Test that sign extension of the low byte/halfword uses a single EXT.W.[BH].
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.extend8_s (local.get 0))))`,
"f",
`ext\\.w\\.b \\$a0, \\$a0`);
codegenTestLOONG64_adhoc(
`(module
(func (export "f") (param i64) (result i64)
(i64.extend16_s (local.get 0))))`,
"f",
`ext\\.w\\.h \\$a0, \\$a0`);
// Test that multiplication by -1 yields negation.
let neg32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.mul (local.get 0) (i32.const -1))))`;
codegenTestLOONG64_adhoc(
neg32,
"f",
`sub.w \\$a0, \\$zero, \\$a0`);
assertEq(wasmEvalText(neg32).exports.f(-37), 37)
assertEq(wasmEvalText(neg32).exports.f(42), -42)
let neg64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const -1))))`;
codegenTestLOONG64_adhoc(
neg64,
"f",
`sub.d \\$a0, \\$zero, \\$a0`);
assertEq(wasmEvalText(neg64).exports.f(-37000000000n), 37000000000n)
assertEq(wasmEvalText(neg64).exports.f(42000000000n), -42000000000n)
// Test that multiplication by zero yields zero.
let zero32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.mul (local.get 0) (i32.const 0))))`;
codegenTestLOONG64_adhoc(
zero32,
"f",
`slli.w \\$a0, \\$zero, 0x0`);
assertEq(wasmEvalText(zero32).exports.f(-37), 0)
assertEq(wasmEvalText(zero32).exports.f(42), 0)
let zero64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const 0))))`;
codegenTestLOONG64_adhoc(
zero64,
"f",
`or \\$a0, \\$zero, \\$zero`);
assertEq(wasmEvalText(zero64).exports.f(-37000000000n), 0n)
assertEq(wasmEvalText(zero64).exports.f(42000000000n), 0n)
// Test that multiplication by one yields no code.
let one32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.mul (local.get 0) (i32.const 1))))`;
codegenTestLOONG64_adhoc(
one32,
"f",
'');
assertEq(wasmEvalText(one32).exports.f(-37), -37)
assertEq(wasmEvalText(one32).exports.f(42), 42)
let one64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const 1))))`;
codegenTestLOONG64_adhoc(
one64,
"f",
'');
assertEq(wasmEvalText(one64).exports.f(-37000000000n), -37000000000n)
assertEq(wasmEvalText(one64).exports.f(42000000000n), 42000000000n)
// Test that multiplication by two yields an ADD.
let double32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.mul (local.get 0) (i32.const 2))))`;
codegenTestLOONG64_adhoc(
double32,
"f",
`add.w \\$a0, \\$a0, \\$a0`);
assertEq(wasmEvalText(double32).exports.f(-37), -74)
assertEq(wasmEvalText(double32).exports.f(42), 84)
let double64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const 2))))`;
codegenTestLOONG64_adhoc(
double64,
"f",
`add.d \\$a0, \\$a0, \\$a0`);
assertEq(wasmEvalText(double64).exports.f(-37000000000n), -74000000000n)
assertEq(wasmEvalText(double64).exports.f(42000000000n), 84000000000n)
// Test that multiplication by four yields a shift.
let quad32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.mul (local.get 0) (i32.const 4))))`;
codegenTestLOONG64_adhoc(
quad32,
"f",
`slli.w \\$a0, \\$a0, 0x2`);
assertEq(wasmEvalText(quad32).exports.f(-37), -148)
assertEq(wasmEvalText(quad32).exports.f(42), 168)
let quad64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const 4))))`;
codegenTestLOONG64_adhoc(
quad64,
"f",
`slli.d \\$a0, \\$a0, 0x2`);
assertEq(wasmEvalText(quad64).exports.f(-37000000000n), -148000000000n)
assertEq(wasmEvalText(quad64).exports.f(42000000000n), 168000000000n)
// Test that multiplication by five yields a shift-add.
let quint32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.mul (local.get 0) (i32.const 5))))`;
codegenTestLOONG64_adhoc(
quint32,
"f",
`slli.w \\$t6, \\$a0, 0x2
add.w \\$a0, \\$t6, \\$a0`);
assertEq(wasmEvalText(quint32).exports.f(-37), -185)
assertEq(wasmEvalText(quint32).exports.f(42), 210)
let quint64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const 5))))`;
codegenTestLOONG64_adhoc(
quint64,
"f",
`alsl.d \\$a0, \\$a0, \\$a0, 0x2`);
assertEq(wasmEvalText(quint64).exports.f(-37000000000n), -185000000000n)
assertEq(wasmEvalText(quint64).exports.f(42000000000n), 210000000000n)
// Test that multiplication by six yields a shift-add for i32 and a
// materialized constant for i64.
let sext32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.mul (local.get 0) (i32.const 6))))`;
codegenTestLOONG64_adhoc(
sext32,
"f",
`slli.w \\$t6, \\$a0, 0x1
add.w \\$a0, \\$t6, \\$a0
slli.w \\$a0, \\$a0, 0x1`);
assertEq(wasmEvalText(sext32).exports.f(-37), -222)
assertEq(wasmEvalText(sext32).exports.f(42), 252)
let sext64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const 6))))`;
codegenTestLOONG64_adhoc(
sext64,
"f",
`addi.w \\$t6, \\$zero, 6
mul.d \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(sext64).exports.f(-37000000000n), -222000000000n)
assertEq(wasmEvalText(sext64).exports.f(42000000000n), 252000000000n)
// Test that multiplication by UINT32_MAX yields x*2^32 - x.
let uint32max64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.mul (local.get 0) (i64.const 0xffffffff))))`;
codegenTestLOONG64_adhoc(
uint32max64,
"f",
`or \\$t6, \\$a0, \\$zero
slli.d \\$a0, \\$a0, 0x20
sub.d \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(uint32max64).exports.f(-37000000000n), BigInt.asIntN(64, -37000000000n * 0xffffffffn))
assertEq(wasmEvalText(uint32max64).exports.f(42000000000n), BigInt.asIntN(64, 42000000000n * 0xffffffffn))
// Test that 0-n yields negation.
let subneg32 =
`(module
(func (export "f") (param i32) (result i32)
(i32.sub (i32.const 0) (local.get 0))))`;
codegenTestLOONG64_adhoc(
subneg32,
"f",
`sub.w \\$a0, \\$zero, \\$a0`);
assertEq(wasmEvalText(subneg32).exports.f(-37), 37)
assertEq(wasmEvalText(subneg32).exports.f(42), -42)
let subneg64 =
`(module
(func (export "f") (param i64) (result i64)
(i64.sub (i64.const 0) (local.get 0))))`;
codegenTestLOONG64_adhoc(
subneg64,
"f",
`sub.d \\$a0, \\$zero, \\$a0`);
assertEq(wasmEvalText(subneg64).exports.f(-37000000000n), 37000000000n)
assertEq(wasmEvalText(subneg64).exports.f(42000000000n), -42000000000n)
// AND followed by `== 0`: check the two operations are merged into a single
// 'AND' + branch on the result, and no comparison result is materialized.
function andEq0(ty, const0) {
return `(module
(func (export "f") (param $p1 ${ty}) (param $p2 ${ty}) (result i32)
(if (result i32) (${ty}.eq (${ty}.and (local.get $p1) (local.get $p2))
(${ty}.const ${const0}))
(then (i32.const 1))
(else (i32.const 0)))))`;
}
for ( [ty, const0, a, b, c, d] of
[['i32', '0', 0, 3, 4, 0x100], ['i64', '0', 0n, 3n, 4n, 0x100n]] ) {
let m = andEq0(ty, const0);
codegenTestLOONG64_adhoc(
m,
"f",
`and \\$t6, \\$a0, \\$a1
bne \\$t6, \\$zero, \\d+ -> ${HEX}+
${NopIns}
bge \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 1
beq \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 0`);
assertEq(wasmEvalText(m).exports.f(a, a), 1)
assertEq(wasmEvalText(m).exports.f(b, c), 1)
assertEq(wasmEvalText(m).exports.f(d, d), 0)
}
// The same with the constant being a contiguous run of one-bits.
// The final shift is not needed when compared against zero.
function andEq0Mask(ty, imm) {
return `(module
(func (export "f") (param $p1 ${ty}) (result i32)
(if (result i32) (${ty}.eq (${ty}.and (local.get $p1) (${ty}.const ${imm}))
(${ty}.const 0))
(then (i32.const 1))
(else (i32.const 0)))))`;
}
for ( [ty, imm, expect] of
[ // low-byte mask => ANDI
['i64', '0xff',
`andi \\$t6, \\$a0, 0xff`],
// low-word mask => BSTRPICK.D
['i64', '0xffffffff',
`bstrpick\\.d \\$t6, \\$a0, 0x1f, 0x0`],
// non-low contiguous mask => BSTRPICK.D
['i64', '0xff00',
`bstrpick\\.d \\$t6, \\$a0, 0xf, 0x8`],
// same for i32
['i32', '0xff00',
`bstrpick\\.d \\$t6, \\$a0, 0xf, 0x8`]] ) {
let m = andEq0Mask(ty, imm);
codegenTestLOONG64_adhoc(
m,
"f",
`${expect}
bne \\$t6, \\$zero, \\d+ -> ${HEX}+
${NopIns}
bge \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 1
beq \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 0`);
}
assertEq(wasmEvalText(andEq0Mask('i64', '0xff')).exports.f(0x1ffn), 0)
assertEq(wasmEvalText(andEq0Mask('i64', '0xff')).exports.f(0x100n), 1)
assertEq(wasmEvalText(andEq0Mask('i64', '0xffffffff')).exports.f(0x100000000n), 1)
assertEq(wasmEvalText(andEq0Mask('i64', '0xff00')).exports.f(0x10000n), 1)
assertEq(wasmEvalText(andEq0Mask('i32', '0xff00')).exports.f(0x10000), 1)
// The same for Signed/NotSigned branches on a masked value.
function andCmpSign0(ty, cmpOp, imm) {
return `(module
(func (export "f") (param $p1 ${ty}) (result i32)
(if (result i32) (${ty}.${cmpOp} (${ty}.and (local.get $p1) (${ty}.const ${imm}))
(${ty}.const 0))
(then (i32.const 1))
(else (i32.const 0)))))`;
}
for ( [ty, cmpOp, imm, expect] of
[
['i32', 'lt_s', '0x80000000',
`bstrpick\\.d \\$a0, \\$a0, 0x3f, 0x1f
slli.d \\$a0, \\$a0, 0x1f
bge \\$a0, \\$zero, \\d+ -> ${HEX}+`],
['i64', 'lt_s', '0x8000000000000000',
`bstrpick\\.d \\$a0, \\$a0, 0x3f, 0x3f
slli.d \\$a0, \\$a0, 0x3f
bge \\$a0, \\$zero, \\d+ -> ${HEX}+`],
['i32', 'ge_s', '0x80000000',
`bstrpick\\.d \\$a0, \\$a0, 0x3f, 0x1f
slli.d \\$a0, \\$a0, 0x1f
blt \\$a0, \\$zero, \\d+ -> ${HEX}+`],
['i64', 'ge_s', '0x8000000000000000',
`bstrpick\\.d \\$a0, \\$a0, 0x3f, 0x3f
slli.d \\$a0, \\$a0, 0x3f
blt \\$a0, \\$zero, \\d+ -> ${HEX}+`],
['i32', 'lt_s', '0x7fffffff',
`bstrpick\\.d \\$a0, \\$a0, 0x1e, 0x0
bge \\$a0, \\$zero, \\d+ -> ${HEX}+`]] ) {
let m = andCmpSign0(ty, cmpOp, imm);
codegenTestLOONG64_adhoc(
m,
"f",
`${expect}
${NopIns}
bge \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 1
beq \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 0`);
}
assertEq(wasmEvalText(andCmpSign0('i32', 'lt_s', '0x80000000')).exports.f(-1), 1)
assertEq(wasmEvalText(andCmpSign0('i32', 'lt_s', '0x80000000')).exports.f(1), 0)
assertEq(wasmEvalText(andCmpSign0('i32', 'lt_s', '0x80000000')).exports.f(0x80000000 | 0), 1)
assertEq(wasmEvalText(andCmpSign0('i32', 'lt_s', '0x80000000')).exports.f(0x7fffffff), 0)
assertEq(wasmEvalText(andCmpSign0('i64', 'lt_s', '0x8000000000000000')).exports.f(-1n), 1)
assertEq(wasmEvalText(andCmpSign0('i64', 'lt_s', '0x8000000000000000')).exports.f(1n), 0)
assertEq(wasmEvalText(andCmpSign0('i64', 'lt_s', '0x8000000000000000')).exports.f(0x8000000000000000n), 1)
assertEq(wasmEvalText(andCmpSign0('i64', 'lt_s', '0x8000000000000000')).exports.f(0x7fffffffffffffffn), 0)
assertEq(wasmEvalText(andCmpSign0('i32', 'ge_s', '0x80000000')).exports.f(-1), 0)
assertEq(wasmEvalText(andCmpSign0('i32', 'ge_s', '0x80000000')).exports.f(1), 1)
assertEq(wasmEvalText(andCmpSign0('i64', 'ge_s', '0x8000000000000000')).exports.f(-1n), 0)
assertEq(wasmEvalText(andCmpSign0('i64', 'ge_s', '0x8000000000000000')).exports.f(1n), 1)
assertEq(wasmEvalText(andCmpSign0('i32', 'lt_s', '0x7fffffff')).exports.f(-1), 0)
assertEq(wasmEvalText(andCmpSign0('i32', 'lt_s', '0x7fffffff')).exports.f(0x7fffffff), 0)
assertEq(wasmEvalText(andCmpSign0('i32', 'lt_s', '0x7fffffff')).exports.f(0), 0)
// The same with one of the args being a constant. Depending on the constant
// we get one of three materialization forms.
function andEq0Const(imm) {
return `(module
(func (export "f") (param $p1 i64) (result i32)
(if (result i32) (i64.eq (i64.and (i64.const ${imm}) (local.get $p1))
(i64.const 0))
(then (i32.const 1))
(else (i32.const 0)))))`;
}
for ( [imm, expect] of
[ // in signed-32 range => LU12I.W + ORI
['0x17654321',
`lu12i.w \\$t6, 95828
ori \\$t6, \\$t6, 0x321`],
// in unsigned-32 range => LU12I.W + BSTRINS.D + ORI
['0x87654321',
`lu12i.w \\$t6, -493996
bstrins.d \\$t6, \\$zero, 0x3f, 0x20
ori \\$t6, \\$t6, 0x321`],
// not in either range => LU12I.W + LU32I.D + ORI
['0x187654321',
`lu12i.w \\$t6, -493996
lu32i.d \\$t6, 1
ori \\$t6, \\$t6, 0x321`]] ) {
codegenTestLOONG64_adhoc(
andEq0Const(imm),
"f",
`${expect}
and \\$t6, \\$a0, \\$t6
bne \\$t6, \\$zero, \\d+ -> ${HEX}+
${NopIns}
bge \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 1
beq \\$zero, \\$zero, \\d+ -> ${HEX}+
${NopIns}
${NopIns}
${NopIns}
addi.w \\$a0, \\$zero, 0`);
}
assertEq(wasmEvalText(andEq0Const('0x17654321')).exports.f(0n), 1)
assertEq(wasmEvalText(andEq0Const('0x17654321')).exports.f(0x17654321n), 0)
assertEq(wasmEvalText(andEq0Const('0x187654321')).exports.f(0x40000000n), 1)
// For integer comparison followed by select, check the comparison is
// evaluated into a register and then applied with MASKEQZ/MASKNEZ.
function cmpSel32vs64(cmpTy, cmpOp, selTy) {
return `(module
(func (export "f")
(param $p1 ${cmpTy}) (param $p2 ${cmpTy})
(param $p3 ${selTy}) (param $p4 ${selTy})
(result ${selTy})
(select (local.get $p3)
(local.get $p4)
(${cmpTy}.${cmpOp} (local.get $p1) (local.get $p2)))
)
)`;
}
for ( [cmpTy, cmpOp, selTy, insns] of
[ ['i32', 'le_s', 'i32',
`slt \\$t6, \\$a1, \\$a0
xori \\$t6, \\$t6, 0x1`],
['i32', 'lt_u', 'i64',
`sltu \\$t6, \\$a0, \\$a1`],
['i64', 'le_s', 'i32',
`slt \\$t6, \\$a1, \\$a0
xori \\$t6, \\$t6, 0x1`],
['i64', 'lt_u', 'i64',
`sltu \\$t6, \\$a0, \\$a1`]
] ) {
let m = cmpSel32vs64(cmpTy, cmpOp, selTy);
codegenTestLOONG64_adhoc(
m,
"f",
`${insns}
maskeqz \\$a0, \\$a2, \\$t6
masknez \\$t6, \\$a3, \\$t6
or \\$a0, \\$a0, \\$t6`);
}
assertEq(wasmEvalText(cmpSel32vs64('i32', 'le_s', 'i32')).exports.f(1, 2, 10, 20), 10)
assertEq(wasmEvalText(cmpSel32vs64('i32', 'le_s', 'i32')).exports.f(2, 1, 10, 20), 20)
assertEq(wasmEvalText(cmpSel32vs64('i32', 'lt_u', 'i64')).exports.f(1, 2, 10n, 20n), 10n)
assertEq(wasmEvalText(cmpSel32vs64('i64', 'le_s', 'i32')).exports.f(1n, 2n, 10, 20), 10)
assertEq(wasmEvalText(cmpSel32vs64('i64', 'lt_u', 'i64')).exports.f(2n, 1n, 10n, 20n), 20n)
// For integer comparison followed by select, check correct use of operands in
// registers vs memory. The first eight params are in registers; the ninth
// and tenth are on the stack.
function select8(selArgT, selArgF, cmpArgL, cmpArgR) {
return `(module
(func (export "f")
(param i64) (param i64) (param i64) (param i64) (param i64)
(param i64) (param i64) (param i64)
(result i64)
(select (local.get ${selArgT}) (local.get ${selArgF})
(i64.eq (local.get ${cmpArgL}) (local.get ${cmpArgR})))))`;
}
let selRR = select8(2, 3, 0, 1);
codegenTestLOONG64_adhoc(
selRR,
"f",
`xor \\$t6, \\$a0, \\$a1
sltui \\$t6, \\$t6, 1
maskeqz \\$a0, \\$a2, \\$t6
masknez \\$t6, \\$a3, \\$t6
or \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(selRR).exports.f(5n, 5n, 10n, 20n, 0n, 0n, 0n, 0n), 10n)
assertEq(wasmEvalText(selRR).exports.f(5n, 6n, 10n, 20n, 0n, 0n, 0n, 0n), 20n)
let selRM = select8(2, 6, 0, 4);
codegenTestLOONG64_adhoc(
selRM,
"f",
`xor \\$t6, \\$a0, \\$a4
sltui \\$t6, \\$t6, 1
maskeqz \\$a0, \\$a2, \\$t6
masknez \\$t6, \\$a6, \\$t6
or \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(selRM).exports.f(5n, 0n, 10n, 0n, 5n, 0n, 20n, 0n), 10n)
assertEq(wasmEvalText(selRM).exports.f(5n, 0n, 10n, 0n, 6n, 0n, 20n, 0n), 20n)
let selMR = select8(6, 3, 4, 1);
codegenTestLOONG64_adhoc(
selMR,
"f",
`xor \\$t6, \\$a4, \\$a1
sltui \\$t6, \\$t6, 1
maskeqz \\$a0, \\$a6, \\$t6
masknez \\$t6, \\$a3, \\$t6
or \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(selMR).exports.f(0n, 5n, 0n, 20n, 5n, 0n, 10n, 0n), 10n)
assertEq(wasmEvalText(selMR).exports.f(0n, 5n, 0n, 20n, 6n, 0n, 10n, 0n), 20n)
let selMM = select8(6, 7, 4, 5);
codegenTestLOONG64_adhoc(
selMM,
"f",
`xor \\$t6, \\$a4, \\$a5
sltui \\$t6, \\$t6, 1
maskeqz \\$a0, \\$a6, \\$t6
masknez \\$t6, \\$a7, \\$t6
or \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(selMM).exports.f(0n, 0n, 0n, 0n, 5n, 5n, 10n, 20n), 10n)
assertEq(wasmEvalText(selMM).exports.f(0n, 0n, 0n, 0n, 5n, 6n, 10n, 20n), 20n)
// A stack-resident select operand or comparison operand is loaded first.
function select10(selArgT, selArgF, cmpArgL, cmpArgR) {
return `(module
(func (export "f")
(param i64) (param i64) (param i64) (param i64) (param i64)
(param i64) (param i64) (param i64) (param i64) (param i64)
(result i64)
(select (local.get ${selArgT}) (local.get ${selArgF})
(i64.eq (local.get ${cmpArgL}) (local.get ${cmpArgR})))))`;
}
let selStack = select10(2, 8, 0, 1);
codegenTestLOONG64_adhoc(
selStack,
"f",
`ld.d \\$a3, \\$fp, 32
xor \\$t6, \\$a0, \\$a1
sltui \\$t6, \\$t6, 1
maskeqz \\$a0, \\$a2, \\$t6
masknez \\$t6, \\$a3, \\$t6
or \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(selStack).exports.f(5n, 5n, 10n, 0n, 0n, 0n, 0n, 0n, 20n, 0n), 10n)
assertEq(wasmEvalText(selStack).exports.f(5n, 6n, 10n, 0n, 0n, 0n, 0n, 0n, 20n, 0n), 20n)
let selStackCmp = select10(2, 3, 8, 1);
codegenTestLOONG64_adhoc(
selStackCmp,
"f",
`ld.d \\$a0, \\$fp, 32
xor \\$t6, \\$a0, \\$a1
sltui \\$t6, \\$t6, 1
maskeqz \\$a0, \\$a2, \\$t6
masknez \\$t6, \\$a3, \\$t6
or \\$a0, \\$a0, \\$t6`);
assertEq(wasmEvalText(selStackCmp).exports.f(5n, 5n, 10n, 20n, 0n, 0n, 0n, 0n, 5n, 0n), 10n)
assertEq(wasmEvalText(selStackCmp).exports.f(5n, 6n, 10n, 20n, 0n, 0n, 0n, 0n, 5n, 0n), 20n)