ion-adhoc-multiplatform.js (17771B)
1 // |jit-test| skip-if: !hasDisassembler() || wasmCompileMode() != "ion" || getBuildConfiguration("windows") || (!getBuildConfiguration("x64") && !getBuildConfiguration("x86") && !getBuildConfiguration("arm64") && !getBuildConfiguration("arm")); include:adhoc-multiplatform-test.js 2 // 3 // These tests push wasm functions through the ion pipe and specify an expected 4 // disassembly output on all 4 primary targets, x64 / x86 / arm64 / arm(32). 5 // Results must be provided for the first 3, but can optionally be skipped 6 // for arm(32). 7 // 8 // Hence: disassembler is needed, compiler must be ion. 9 // 10 // Windows is disallowed because the argument registers are different from on 11 // Linux, and matching both is both difficult and not of much value. 12 13 // Tests are "end-to-end" in the sense that we don't care whether the 14 // tested-for code improvement is done by MIR optimisation, or later in the 15 // pipe. Observed defects are marked with FIXMEs for future easy finding. 16 17 18 // Note that identities involving AND, OR and XOR are tested by 19 // binop-x64-ion-folding.js 20 21 // Multiplication with magic constant on the left 22 // 23 // 0 * x => 0 24 // 1 * x => x 25 // -1 * x => -x 26 // 2 * x => x + x 27 // 4 * x => x << 2 28 29 codegenTestMultiplatform_adhoc( 30 `(module (func (export "mul32_zeroL") (param $p1 i32) (result i32) 31 (i32.mul (i32.const 0) (local.get $p1))))`, 32 "mul32_zeroL", 33 {x64: `xor %eax, %eax`, 34 x86: `xor %eax, %eax`, 35 arm64: `mov w0, wzr`, 36 arm: `mov r0, #0`}, 37 {x86: {no_prefix:true}} 38 ); 39 codegenTestMultiplatform_adhoc( 40 `(module (func (export "mul64_zeroL") (param $p1 i64) (result i64) 41 (i64.mul (i64.const 0) (local.get $p1))))`, 42 "mul64_zeroL", 43 // FIXME zero-creation insns could be improved 44 {x64: `xor %rax, %rax`, // REX.W is redundant 45 x86: `xor %eax, %eax 46 xor %edx, %edx`, 47 arm64: `mov x0, xzr`, 48 arm: `mov r0, #0 49 mov r1, #0` }, 50 {x86: {no_prefix:true}} 51 ); 52 53 codegenTestMultiplatform_adhoc( 54 `(module (func (export "mul32_oneL") (param $p1 i32) (result i32) 55 (i32.mul (i32.const 1) (local.get $p1))))`, 56 "mul32_oneL", 57 {x64: // We move edi to eax unnecessarily via ecx (bug 1752520). 58 // Presumably because the folding 1 * x => x is done at the LIR 59 // level, not the MIR level, hence the now-pointless WasmParameter 60 // node is not DCE'd away, since DCE only happens at the MIR level. 61 // In fact all targets suffer from the latter problem, but on x86 62 // no_prefix_x86:true hides it, and on arm32/64 the pointless move 63 // is correctly transformed by RA into a no-op. 64 `mov %edi, %ecx 65 mov %ecx, %eax`, 66 x86: `movl 0x10\\(%rbp\\), %eax`, 67 arm64: ``, 68 arm: ``}, 69 {x86: {no_prefix:true}} 70 ); 71 codegenTestMultiplatform_adhoc( 72 `(module (func (export "mul64_oneL") (param $p1 i64) (result i64) 73 (i64.mul (i64.const 1) (local.get $p1))))`, 74 "mul64_oneL", 75 {x64: `mov %rdi, %rcx 76 mov %rcx, %rax`, 77 x86: `movl 0x14\\(%rbp\\), %edx 78 movl 0x10\\(%rbp\\), %eax`, 79 arm64: ``, 80 arm: ``}, 81 {x86: {no_prefix:true}} 82 ); 83 84 codegenTestMultiplatform_adhoc( 85 `(module (func (export "mul32_minusOneL") (param $p1 i32) (result i32) 86 (i32.mul (i32.const -1) (local.get $p1))))`, 87 "mul32_minusOneL", 88 {x64: `neg %eax`, 89 x86: `neg %eax`, 90 arm64: `neg w0, w0`, 91 arm: `rsb r0, r0, #0`}, 92 {x86: {no_prefix:true}, x64: {no_prefix:true}} 93 ); 94 codegenTestMultiplatform_adhoc( 95 `(module (func (export "mul64_minusOneL") (param $p1 i64) (result i64) 96 (i64.mul (i64.const -1) (local.get $p1))))`, 97 "mul64_minusOneL", 98 {x64: `mov %rdi, %rcx 99 mov %rcx, %rax 100 neg %rax`, 101 x86: `neg %eax 102 adc \\$0x00, %edx 103 neg %edx`, 104 arm64: `neg x0, x0`, 105 arm: `rsbs r0, r0, #0 106 rsc r1, r1, #0`}, 107 {x86: {no_prefix:true}} 108 ); 109 110 codegenTestMultiplatform_adhoc( 111 `(module (func (export "mul32_twoL") (param $p1 i32) (result i32) 112 (i32.mul (i32.const 2) (local.get $p1))))`, 113 "mul32_twoL", 114 {x64: `lea \\(%rdi,%rdi,1\\), %eax`, 115 x86: `movl 0x10\\(%rbp\\), %eax 116 add %eax, %eax`, 117 arm64: `add w0, w0, w0`, 118 arm: `adds r0, r0, r0`}, 119 {x86: {no_prefix:true}} 120 ); 121 codegenTestMultiplatform_adhoc( 122 `(module (func (export "mul64_twoL") (param $p1 i64) (result i64) 123 (i64.mul (i64.const 2) (local.get $p1))))`, 124 "mul64_twoL", 125 {x64: `lea \\(%rdi,%rdi,1\\), %rax`, 126 x86: `movl 0x14\\(%rbp\\), %edx 127 movl 0x10\\(%rbp\\), %eax 128 add %eax, %eax 129 adc %edx, %edx`, 130 arm64: `add x0, x0, x0`, 131 arm: `adds r0, r0, r0 132 adc r1, r1, r1`}, 133 {x86: {no_prefix:true}} 134 ); 135 136 codegenTestMultiplatform_adhoc( 137 `(module (func (export "mul32_fourL") (param $p1 i32) (result i32) 138 (i32.mul (i32.const 4) (local.get $p1))))`, 139 "mul32_fourL", 140 {x64: `lea \\(,%rdi,4\\), %eax`, 141 x86: `movl 0x10\\(%rbp\\), %eax 142 shl \\$0x02, %eax`, 143 arm64: `lsl w0, w0, #2`, 144 arm: `mov r0, r0, lsl #2`}, 145 {x86: {no_prefix:true}} 146 ); 147 codegenTestMultiplatform_adhoc( 148 `(module (func (export "mul64_fourL") (param $p1 i64) (result i64) 149 (i64.mul (i64.const 4) (local.get $p1))))`, 150 "mul64_fourL", 151 {x64: `lea \\(,%rdi,4\\), %rax`, 152 x86: `movl 0x14\\(%rbp\\), %edx 153 movl 0x10\\(%rbp\\), %eax 154 shld \\$0x02, %eax, %edx 155 shl \\$0x02, %eax`, 156 arm64: `lsl x0, x0, #2`, 157 arm: `mov r1, r1, lsl #2 158 orr r1, r1, r0, lsr #30 159 mov r0, r0, lsl #2`}, 160 {x86: {no_prefix:true}} 161 ); 162 163 // Multiplication with magic constant on the right 164 // 165 // x * 0 => 0 166 // x * 1 => x 167 // x * -1 => -x 168 // x * 2 => x + x 169 // x * 4 => x << 2 170 171 codegenTestMultiplatform_adhoc( 172 `(module (func (export "mul32_zeroR") (param $p1 i32) (result i32) 173 (i32.mul (local.get $p1) (i32.const 0))))`, 174 "mul32_zeroR", 175 {x64: `xor %eax, %eax`, 176 x86: `xor %eax, %eax`, 177 arm64: `mov w0, wzr`, 178 arm: `mov r0, #0`}, 179 {x86: {no_prefix:true}} 180 ); 181 codegenTestMultiplatform_adhoc( 182 `(module (func (export "mul64_zeroR") (param $p1 i64) (result i64) 183 (i64.mul (local.get $p1) (i64.const 0))))`, 184 "mul64_zeroR", 185 {x64: `xor %rax, %rax`, // REX.W is redundant 186 x86: `xor %eax, %eax 187 xor %edx, %edx`, 188 arm64: `mov x0, xzr`, 189 arm: `mov r0, #0 190 mov r1, #0` }, 191 {x86: {no_prefix:true}} 192 ); 193 194 codegenTestMultiplatform_adhoc( 195 `(module (func (export "mul32_oneR") (param $p1 i32) (result i32) 196 (i32.mul (local.get $p1) (i32.const 1))))`, 197 "mul32_oneR", 198 {x64: `mov %edi, %ecx 199 mov %ecx, %eax`, 200 x86: `movl 0x10\\(%rbp\\), %eax`, 201 arm64: ``, 202 arm: ``}, 203 {x86: {no_prefix:true}} 204 ); 205 codegenTestMultiplatform_adhoc( 206 `(module (func (export "mul64_oneR") (param $p1 i64) (result i64) 207 (i64.mul (local.get $p1) (i64.const 1))))`, 208 "mul64_oneR", 209 {x64: `mov %rdi, %rcx 210 mov %rcx, %rax`, 211 x86: `movl 0x14\\(%rbp\\), %edx 212 movl 0x10\\(%rbp\\), %eax`, 213 arm64: ``, 214 arm: ``}, 215 {x86: {no_prefix:true}} 216 ); 217 218 codegenTestMultiplatform_adhoc( 219 `(module (func (export "mul32_minusOneR") (param $p1 i32) (result i32) 220 (i32.mul (local.get $p1) (i32.const -1))))`, 221 "mul32_minusOneR", 222 {x64: `neg %eax`, 223 x86: `neg %eax`, 224 arm64: `neg w0, w0`, 225 arm: `rsb r0, r0, #0`}, 226 {x86: {no_prefix:true}, x64: {no_prefix:true}} 227 ); 228 codegenTestMultiplatform_adhoc( 229 `(module (func (export "mul64_minusOneR") (param $p1 i64) (result i64) 230 (i64.mul (local.get $p1) (i64.const -1))))`, 231 "mul64_minusOneR", 232 {x64: `mov %rdi, %rcx 233 mov %rcx, %rax 234 neg %rax`, 235 x86: `neg %eax 236 adc \\$0x00, %edx 237 neg %edx`, 238 arm64: `neg x0, x0`, 239 arm: `rsbs r0, r0, #0 240 rsc r1, r1, #0`}, 241 {x86: {no_prefix:true}} 242 ); 243 244 codegenTestMultiplatform_adhoc( 245 `(module (func (export "mul32_twoR") (param $p1 i32) (result i32) 246 (i32.mul (local.get $p1) (i32.const 2))))`, 247 "mul32_twoR", 248 {x64: `lea \\(%rdi,%rdi,1\\), %eax`, 249 x86: `movl 0x10\\(%rbp\\), %eax 250 add %eax, %eax`, 251 arm64: `add w0, w0, w0`, 252 arm: `adds r0, r0, r0`}, 253 {x86: {no_prefix:true}} 254 ); 255 codegenTestMultiplatform_adhoc( 256 `(module (func (export "mul64_twoR") (param $p1 i64) (result i64) 257 (i64.mul (local.get $p1) (i64.const 2))))`, 258 "mul64_twoR", 259 {x64: `lea \\(%rdi,%rdi,1\\), %rax`, 260 x86: `movl 0x14\\(%rbp\\), %edx 261 movl 0x10\\(%rbp\\), %eax 262 add %eax, %eax 263 adc %edx, %edx`, 264 arm64: `add x0, x0, x0`, 265 arm: `adds r0, r0, r0 266 adc r1, r1, r1`}, 267 {x86: {no_prefix:true}} 268 ); 269 270 codegenTestMultiplatform_adhoc( 271 `(module (func (export "mul32_fourR") (param $p1 i32) (result i32) 272 (i32.mul (local.get $p1) (i32.const 4))))`, 273 "mul32_fourR", 274 {x64: `lea \\(,%rdi,4\\), %eax`, 275 x86: `movl 0x10\\(%rbp\\), %eax 276 shl \\$0x02, %eax`, 277 arm64: `lsl w0, w0, #2`, 278 arm: `mov r0, r0, lsl #2`}, 279 {x86: {no_prefix:true}} 280 ); 281 codegenTestMultiplatform_adhoc( 282 `(module (func (export "mul64_fourR") (param $p1 i64) (result i64) 283 (i64.mul (local.get $p1) (i64.const 4))))`, 284 "mul64_fourR", 285 {x64: `lea \\(,%rdi,4\\), %rax`, 286 x86: `movl 0x14\\(%rbp\\), %edx 287 movl 0x10\\(%rbp\\), %eax 288 shld \\$0x02, %eax, %edx 289 shl \\$0x02, %eax`, 290 arm64: `lsl x0, x0, #2`, 291 arm: `mov r1, r1, lsl #2 292 orr r1, r1, r0, lsr #30 293 mov r0, r0, lsl #2` 294 }, 295 {x86: {no_prefix:true}} 296 ); 297 298 // Shifts by zero (the right arg is zero) 299 // 300 // x >> 0 => x (any shift kind: shl, shrU, shrS) 301 302 codegenTestMultiplatform_adhoc( 303 `(module (func (export "shl32_zeroR") (param $p1 i32) (result i32) 304 (i32.shl (local.get $p1) (i32.const 0))))`, 305 "shl32_zeroR", 306 // FIXME check these are consistently folded out at the MIR level 307 {x64: `mov %edi, %ecx 308 mov %ecx, %eax`, 309 x86: `movl 0x10\\(%rbp\\), %eax`, 310 arm64: `mov w0, w0`, 311 arm: `` // no-op 312 }, 313 {x86: {no_prefix:true}} 314 ); 315 codegenTestMultiplatform_adhoc( 316 `(module (func (export "shl64_zeroR") (param $p1 i64) (result i64) 317 (i64.shl (local.get $p1) (i64.const 0))))`, 318 "shl64_zeroR", 319 // FIXME why is this code so much better than the 32-bit case? 320 {x64: `mov %rdi, %rcx 321 mov %rcx, %rax`, 322 x86: `movl 0x14\\(%rbp\\), %edx 323 movl 0x10\\(%rbp\\), %eax`, 324 arm64: ``, // no-op 325 arm: `` // no-op 326 }, 327 {x86: {no_prefix:true}} 328 ); 329 330 codegenTestMultiplatform_adhoc( 331 `(module (func (export "shrU32_zeroR") (param $p1 i32) (result i32) 332 (i32.shr_u (local.get $p1) (i32.const 0))))`, 333 "shrU32_zeroR", 334 {x64: `mov %edi, %ecx 335 mov %ecx, %eax`, 336 x86: `movl 0x10\\(%rbp\\), %eax`, 337 arm64: `mov w0, w0`, 338 arm: `` 339 }, 340 {x86: {no_prefix:true}} 341 ); 342 codegenTestMultiplatform_adhoc( 343 `(module (func (export "shrU64_zeroR") (param $p1 i64) (result i64) 344 (i64.shr_u (local.get $p1) (i64.const 0))))`, 345 "shrU64_zeroR", 346 {x64: `mov %rdi, %rcx 347 mov %rcx, %rax`, 348 x86: `movl 0x14\\(%rbp\\), %edx 349 movl 0x10\\(%rbp\\), %eax`, 350 arm64: ``, 351 arm: `` 352 }, 353 {x86: {no_prefix:true}} 354 ); 355 356 codegenTestMultiplatform_adhoc( 357 `(module (func (export "shrS32_zeroR") (param $p1 i32) (result i32) 358 (i32.shr_s (local.get $p1) (i32.const 0))))`, 359 "shrS32_zeroR", 360 {x64: `mov %edi, %ecx 361 mov %ecx, %eax`, 362 x86: `movl 0x10\\(%rbp\\), %eax`, 363 arm64: `mov w0, w0`, 364 arm: `` 365 }, 366 {x86: {no_prefix:true}} 367 ); 368 codegenTestMultiplatform_adhoc( 369 `(module (func (export "shrS64_zeroR") (param $p1 i64) (result i64) 370 (i64.shr_s (local.get $p1) (i64.const 0))))`, 371 "shrS64_zeroR", 372 {x64: `mov %rdi, %rcx 373 mov %rcx, %rax`, 374 x86: `movl 0x14\\(%rbp\\), %edx 375 movl 0x10\\(%rbp\\), %eax`, 376 arm64: ``, 377 arm: `` 378 }, 379 {x86: {no_prefix:true}} 380 ); 381 382 // Identities involving addition 383 // 384 // x + 0 => x 385 // 0 + x => x 386 // x + x => x << 1 387 388 codegenTestMultiplatform_adhoc( 389 `(module (func (export "add32_zeroR") (param $p1 i32) (result i32) 390 (i32.add (local.get $p1) (i32.const 0))))`, 391 "add32_zeroR", 392 {x64: `mov %edi, %ecx 393 mov %ecx, %eax`, 394 x86: `movl 0x10\\(%rbp\\), %eax`, 395 arm64: ``, 396 arm: `` 397 }, 398 {x86: {no_prefix:true}} 399 ); 400 codegenTestMultiplatform_adhoc( 401 `(module (func (export "add64_zeroR") (param $p1 i64) (result i64) 402 (i64.add (local.get $p1) (i64.const 0))))`, 403 "add64_zeroR", 404 {x64: `mov %rdi, %rcx 405 mov %rcx, %rax`, 406 x86: `movl 0x14\\(%rbp\\), %edx 407 movl 0x10\\(%rbp\\), %eax`, 408 arm64: ``, 409 arm: `` 410 }, 411 {x86: {no_prefix:true}} 412 ); 413 414 codegenTestMultiplatform_adhoc( 415 `(module (func (export "add32_zeroL") (param $p1 i32) (result i32) 416 (i32.add (i32.const 0) (local.get $p1))))`, 417 "add32_zeroL", 418 {x64: `mov %edi, %ecx 419 mov %ecx, %eax`, 420 x86: `movl 0x10\\(%rbp\\), %eax`, 421 arm64: ``, 422 arm: `` 423 }, 424 {x86: {no_prefix:true}} 425 ); 426 codegenTestMultiplatform_adhoc( 427 `(module (func (export "add64_zeroL") (param $p1 i64) (result i64) 428 (i64.add (i64.const 0) (local.get $p1))))`, 429 "add64_zeroL", 430 {x64: `mov %rdi, %rcx 431 mov %rcx, %rax`, 432 x86: `movl 0x14\\(%rbp\\), %edx 433 movl 0x10\\(%rbp\\), %eax`, 434 arm64: ``, 435 arm: `` 436 }, 437 {x86: {no_prefix:true}} 438 ); 439 440 codegenTestMultiplatform_adhoc( 441 `(module (func (export "add32_self") (param $p1 i32) (result i32) 442 (i32.add (local.get $p1) (local.get $p1))))`, 443 "add32_self", 444 {x64: `mov %edi, %ecx 445 mov %ecx, %eax 446 add %ecx, %eax`, 447 x86: `movl 0x10\\(%rbp\\), %eax 448 addl 0x10\\(%rbp\\), %eax`, 449 arm64: `add w0, w0, w0`, 450 arm: `adds r0, r0, r0 ` 451 }, 452 {x86: {no_prefix:true}} 453 ); 454 codegenTestMultiplatform_adhoc( 455 `(module (func (export "add64_self") (param $p1 i64) (result i64) 456 (i64.add (local.get $p1) (local.get $p1))))`, 457 "add64_self", 458 // FIXME outstandingly bad 32-bit sequences, probably due to the RA 459 {x64: `mov %rdi, %rcx 460 mov %rcx, %rax 461 add %rcx, %rax`, 462 x86: // -0x21524111 is 0xDEADBEEF 463 `movl 0x14\\(%rbp\\), %ebx 464 movl 0x10\\(%rbp\\), %ecx 465 mov \\$-0x21524111, %edi 466 movl 0x14\\(%rbp\\), %edx 467 movl 0x10\\(%rbp\\), %eax 468 add %ecx, %eax 469 adc %ebx, %edx`, 470 arm64: `add x0, x0, x0`, 471 arm: // play Musical Chairs for a while 472 `mov r3, r1 473 mov r2, r0 474 mov r5, r3 475 mov r4, r2 476 mov r1, r3 477 mov r0, r2 478 adds r0, r0, r4 479 adc r1, r1, r5` 480 }, 481 {x86: {no_prefix:true}} 482 ); 483 484 // Identities involving subtraction 485 // 486 // x - 0 => x 487 // 0 - x => -x 488 // x - x => 0 489 490 codegenTestMultiplatform_adhoc( 491 `(module (func (export "sub32_zeroR") (param $p1 i32) (result i32) 492 (i32.sub (local.get $p1) (i32.const 0))))`, 493 "sub32_zeroR", 494 {x64: `mov %edi, %ecx 495 mov %ecx, %eax`, 496 x86: `movl 0x10\\(%rbp\\), %eax`, 497 arm64: ``, 498 arm: `` 499 }, 500 {x86: {no_prefix:true}} 501 ); 502 codegenTestMultiplatform_adhoc( 503 `(module (func (export "sub64_zeroR") (param $p1 i64) (result i64) 504 (i64.sub (local.get $p1) (i64.const 0))))`, 505 "sub64_zeroR", 506 {x64: `mov %rdi, %rcx 507 mov %rcx, %rax`, 508 x86: `movl 0x14\\(%rbp\\), %edx 509 movl 0x10\\(%rbp\\), %eax`, 510 arm64: ``, 511 arm: `` 512 }, 513 {x86: {no_prefix:true}} 514 ); 515 516 codegenTestMultiplatform_adhoc( 517 `(module (func (export "sub32_zeroL") (param $p1 i32) (result i32) 518 (i32.sub (i32.const 0) (local.get $p1))))`, 519 "sub32_zeroL", 520 {x64: `mov %edi, %ecx 521 mov %ecx, %eax 522 neg %eax`, 523 x86: `movl 0x10\\(%rbp\\), %eax 524 neg %eax`, 525 arm64: `neg w0, w0 `, 526 arm: `rsb r0, r0, #0` 527 }, 528 {x86: {no_prefix:true}} 529 ); 530 codegenTestMultiplatform_adhoc( 531 `(module (func (export "sub64_zeroL") (param $p1 i64) (result i64) 532 (i64.sub (i64.const 0) (local.get $p1))))`, 533 "sub64_zeroL", 534 {x64: `mov %rdi, %rcx 535 mov %rcx, %rax 536 neg %rax`, 537 x86: `movl 0x14\\(%rbp\\), %edx 538 movl 0x10\\(%rbp\\), %eax 539 neg %eax 540 adc \\$0x00, %edx 541 neg %edx`, 542 arm64: `neg x0, x0`, 543 arm: `rsbs r0, r0, #0 544 rsc r1, r1, #0` 545 }, 546 {x86: {no_prefix:true}} 547 ); 548 549 codegenTestMultiplatform_adhoc( 550 `(module (func (export "sub32_self") (param $p1 i32) (result i32) 551 (i32.sub (local.get $p1) (local.get $p1))))`, 552 "sub32_self", 553 {x64: `xor %eax, %eax`, 554 x86: `xor %eax, %eax`, 555 arm64: `mov w0, #0x0`, 556 arm: `mov r0, #0` 557 }, 558 {x86: {no_prefix:true}} 559 ); 560 codegenTestMultiplatform_adhoc( 561 `(module (func (export "sub64_self") (param $p1 i64) (result i64) 562 (i64.sub (local.get $p1) (local.get $p1))))`, 563 "sub64_self", 564 {x64: `xor %eax, %eax`, 565 x86: `xor %eax, %eax 566 xor %edx, %edx`, 567 arm64: `mov x0, #0x0`, 568 arm: `mov r0, #0 569 mov r1, #0` 570 }, 571 {x86: {no_prefix:true}} 572 );