testFloat32.js (12140B)
1 // |jit-test| --baseline-warmup-threshold=20 2 3 // This test checks that we are able to optimize float32 inputs. As 4 // GetElementIC (float32 array accesses) output is not specialized with Float32 5 // output types, we should not force inline caches. 6 if (getJitCompilerOptions()["ion.forceinlineCaches"]) 7 setJitCompilerOption("ion.forceinlineCaches", 0); 8 9 // Fuzz tests 10 (function(){ 11 // 12 (function(){ 13 var g = {}; 14 x = new Float32Array() 15 Function('g', "g.o = x[1]")(g); 16 })(); 17 // 18 (function() { 19 var g = new Float32Array(16); 20 var h = new Float64Array(16); 21 var farrays = [ g, h ]; 22 for (aridx = 0; aridx < farrays.length; ++aridx) { 23 ar = farrays[aridx]; 24 !(ar[ar.length-2] == (NaN / Infinity)[ar.length-2]) 25 } 26 })(); 27 // 28 (function () { 29 var v = new Float32Array(32); 30 for (var i = 0; i < v.length; ++i) 31 v[i] = i; 32 var t = (false ); 33 for (var i = 0; i < i .length; ++i) 34 t += v[i]; 35 })(); 36 // 37 (function() { 38 x = y = {}; 39 z = new Float32Array(6) 40 for (c in this) { 41 Array.prototype.unshift.call(x, new ArrayBuffer()) 42 } 43 Array.prototype.sort.call(x, (function (j) { 44 y.s = z[2] 45 })) 46 })(); 47 // 48 (function() { 49 // bug 1134298 50 for (var k = 0; k < 1; k++) { 51 Math.fround(Math.ceil(Math.fround(Math.acos(3.0)))) 52 } 53 })(); 54 })(); 55 // 56 // ION TESTS 57 // 58 // The assertFloat32 function is deactivated in --ion-eager mode, as the first time, the function Math.fround 59 // would be guarded against modifications (typeguard on Math and then on fround). In this case, Math.fround is 60 // not inlined and the compiler will consider the return value to be a double, not a float32, making the 61 // assertions fail. Note that as assertFloat32 is declared unsafe for fuzzing, this can't happen in fuzzed code. 62 // 63 // To be able to test it, we still need ion compilation though. A nice solution 64 // is to manually lower the ion warm-up trigger. 65 setJitCompilerOption("ion.warmup.trigger", 50); 66 67 function test(f) { 68 f32[0] = .5; 69 for(var n = 110; n; n--) 70 f(); 71 } 72 73 var f32 = new Float32Array(4); 74 var f64 = new Float64Array(4); 75 76 function acceptAdd() { 77 var use = f32[0] + 1; 78 assertFloat32(use, true); 79 f32[0] = use; 80 } 81 test(acceptAdd); 82 83 function acceptAddSeveral() { 84 var sum1 = f32[0] + 0.5; 85 var sum2 = f32[0] + 0.5; 86 f32[0] = sum1; 87 f32[0] = sum2; 88 assertFloat32(sum1, true); 89 assertFloat32(sum2, true); 90 } 91 test(acceptAddSeveral); 92 93 function acceptAddVar() { 94 var x = f32[0] + 1; 95 f32[0] = x; 96 f32[1] = x; 97 assertFloat32(x, true); 98 } 99 test(acceptAddVar); 100 101 function refuseAddCst() { 102 var x = f32[0] + 1234567890; // this constant can't be precisely represented as a float32 103 f32[0] = x; 104 assertFloat32(x, false); 105 } 106 test(refuseAddCst); 107 108 function refuseAddVar() { 109 var x = f32[0] + 1; 110 f32[0] = x; 111 f32[1] = x; 112 f64[1] = x; // non consumer 113 assertFloat32(x, false); 114 } 115 test(refuseAddVar); 116 117 function refuseAddStore64() { 118 var x = f32[0] + 1; 119 f64[0] = x; // non consumer 120 f32[0] = f64[0]; 121 assertFloat32(x, false); 122 } 123 test(refuseAddStore64); 124 125 function refuseAddStoreObj() { 126 var o = {} 127 var x = f32[0] + 1; 128 o.x = x; // non consumer 129 f32[0] = o['x']; 130 assertFloat32(x, false); 131 } 132 test(refuseAddStoreObj); 133 134 function refuseAddSeveral() { 135 var sum = (f32[0] + 2) - 1; // second addition is not a consumer 136 f32[0] = sum; 137 assertFloat32(sum, false); 138 } 139 test(refuseAddSeveral); 140 141 function refuseAddFunctionCall() { 142 function plusOne(x) { return Math.cos(x+1)*13.37; } 143 var res = plusOne(f32[0]); // func call is not a consumer 144 f32[0] = res; 145 assertFloat32(res, false); 146 } 147 test(refuseAddFunctionCall); 148 149 function acceptSqrt() { 150 var res = Math.sqrt(f32[0]); 151 assertFloat32(res, true); 152 f32[0] = res; 153 } 154 test(acceptSqrt); 155 156 function refuseSqrt() { 157 var res = Math.sqrt(f32[0]); 158 assertFloat32(res, false); 159 f32[0] = res + 1; 160 } 161 test(refuseSqrt); 162 163 function acceptMin() { 164 var res = Math.min(f32[0], f32[1]); 165 assertFloat32(res, true); 166 f64[0] = res; 167 } 168 test(acceptMin); 169 170 // In theory, we could do it, as Math.min/max actually behave as a Phi (it's a 171 // float32 producer iff its inputs are producers, it's a consumer iff its uses 172 // are consumers). In practice, this would involve some overhead for big chains 173 // of min/max. 174 function refuseMinAdd() { 175 var res = Math.min(f32[0], f32[1]) + f32[2]; 176 assertFloat32(res, false); 177 f32[3] = res; 178 } 179 test(refuseMinAdd); 180 181 function acceptSeveralMinMax() { 182 var x = Math.min(f32[0], f32[1]); 183 var y = Math.max(f32[2], f32[3]); 184 var res = Math.min(x, y); 185 assertFloat32(res, true); 186 f64[0] = res; 187 } 188 test(acceptSeveralMinMax); 189 190 function acceptSeveralMinMax2() { 191 var res = Math.min(f32[0], f32[1], f32[2], f32[3]); 192 assertFloat32(res, true); 193 f64[0] = res; 194 } 195 test(acceptSeveralMinMax2); 196 197 function partialMinMax() { 198 var x = Math.min(f32[0], f32[1]); 199 var y = Math.min(f64[0], f32[1]); 200 var res = Math.min(x, y); 201 assertFloat32(x, true); 202 assertFloat32(y, false); 203 assertFloat32(res, false); 204 f64[0] = res; 205 } 206 test(partialMinMax); 207 208 function refuseSeveralMinMax() { 209 var res = Math.min(f32[0], f32[1] + f32[2], f32[2], f32[3]); 210 assertFloat32(res, false); 211 f64[0] = res; 212 } 213 test(refuseSeveralMinMax); 214 215 function refuseMin() { 216 var res = Math.min(f32[0], 42.13 + f32[1]); 217 assertFloat32(res, false); 218 f64[0] = res; 219 } 220 test(refuseMin); 221 222 function acceptMax() { 223 var res = Math.max(f32[0], f32[1]); 224 assertFloat32(res, true); 225 f64[0] = res; 226 } 227 test(acceptMax); 228 229 function refuseMax() { 230 var res = Math.max(f32[0], 42.13 + f32[1]); 231 assertFloat32(res, false); 232 f64[0] = res; 233 } 234 test(refuseMax); 235 236 function acceptAbs() { 237 var res = Math.abs(f32[0]); 238 assertFloat32(res, true); 239 f32[0] = res; 240 } 241 test(acceptAbs); 242 243 function refuseAbs() { 244 var res = Math.abs(f32[0]); 245 assertFloat32(res, false); 246 f64[0] = res + 1; 247 } 248 test(refuseAbs); 249 250 function acceptFilterTypeSet() { 251 var res = f32[0]; 252 if (!res) { 253 } else { 254 f32[0] = res; 255 assertFloat32(res, true); 256 } 257 } 258 test(acceptFilterTypeSet); 259 260 function acceptFilterTypeSet2() { 261 var res = f32[0]; 262 if (!res) { 263 } else { 264 var res1 = Math.abs(res); 265 f32[0] = res1; 266 assertFloat32(res1, true); 267 } 268 } 269 test(acceptFilterTypeSet2); 270 271 function refuseFilterTypeSet() { 272 var res = f32[0]; 273 if (!res) { 274 } else { 275 var res1 = Math.abs(res); 276 f64[0] = res1 + 1; 277 assertFloat32(res1, false); 278 } 279 } 280 test(refuseFilterTypeSet); 281 282 function refuseTrigo() { 283 var res = Math.cos(f32[0]); 284 f32[0] = res; 285 assertFloat32(res, false); 286 287 var res = Math.sin(f32[0]); 288 f32[0] = res; 289 assertFloat32(res, false); 290 291 var res = Math.tan(f32[0]); 292 f32[0] = res; 293 assertFloat32(res, false); 294 295 var res = Math.acos(f32[0]); 296 f32[0] = res; 297 assertFloat32(res, false); 298 299 var res = Math.asin(f32[0]); 300 f32[0] = res; 301 assertFloat32(res, false); 302 303 res = Math.atan(f32[0]); 304 f32[0] = res; 305 assertFloat32(res, false); 306 } 307 test(refuseTrigo); 308 309 function acceptCeil() { 310 // Specialize for floating-point output. 311 f32[0] = NaN; 312 f32[1] = Infinity; 313 f32[2] = -0; 314 f32[3] = 0.5; 315 316 var res = Math.ceil(f32[0]); 317 f32[0] = res; 318 assertFloat32(res, true); 319 } 320 test(acceptCeil); 321 322 function acceptFloor() { 323 // Specialize for floating-point output. 324 f32[0] = NaN; 325 f32[1] = Infinity; 326 f32[2] = -0; 327 f32[3] = 0.5; 328 329 var res = Math.floor(f32[0]); 330 f32[0] = res; 331 assertFloat32(res, true); 332 } 333 test(acceptFloor); 334 335 function acceptRound() { 336 // Specialize for floating-point output. 337 f32[0] = NaN; 338 f32[1] = Infinity; 339 f32[2] = -0; 340 f32[3] = 0.5; 341 342 var res = Math.round(f32[0]); 343 f32[0] = res; 344 assertFloat32(res, true); 345 } 346 test(acceptRound); 347 348 function acceptTrunc() { 349 // Specialize for floating-point output. 350 f32[0] = NaN; 351 f32[1] = Infinity; 352 f32[2] = -0; 353 f32[3] = 0.5; 354 355 var res = Math.trunc(f32[0]); 356 f32[0] = res; 357 assertFloat32(res, true); 358 } 359 test(acceptTrunc); 360 361 function refuseMath() { 362 var res = Math.log(f32[0]); 363 f32[0] = res; 364 assertFloat32(res, false); 365 366 var res = Math.log10(f32[0]); 367 f32[0] = res; 368 assertFloat32(res, false); 369 370 res = Math.log2(f32[0]); 371 f32[0] = res; 372 assertFloat32(res, false); 373 374 res = Math.log1p(f32[0]); 375 f32[0] = res; 376 assertFloat32(res, false); 377 378 res = Math.exp(f32[0]); 379 f32[0] = res; 380 assertFloat32(res, false); 381 382 res = Math.expm1(f32[0]); 383 f32[0] = res; 384 assertFloat32(res, false); 385 386 res = Math.cosh(f32[0]); 387 f32[0] = res; 388 assertFloat32(res, false); 389 390 res = Math.sinh(f32[0]); 391 f32[0] = res; 392 assertFloat32(res, false); 393 394 res = Math.tanh(f32[0]); 395 f32[0] = res; 396 assertFloat32(res, false); 397 398 res = Math.acosh(f32[0]); 399 f32[0] = res; 400 assertFloat32(res, false); 401 402 res = Math.asinh(f32[0]); 403 f32[0] = res; 404 assertFloat32(res, false); 405 406 res = Math.atanh(f32[0]); 407 f32[0] = res; 408 assertFloat32(res, false); 409 410 res = Math.cbrt(f32[0]); 411 f32[0] = res; 412 assertFloat32(res, false); 413 414 res = Math.sign(f32[0]); 415 f32[0] = res; 416 assertFloat32(res, false); 417 } 418 test(refuseMath); 419 420 function refuseLoop() { 421 var res = f32[0], 422 n = 10; 423 while (n--) { 424 res = res + 1; // this loop is equivalent to several additions => second addition is not a consumer 425 assertFloat32(res, false); 426 } 427 assertFloat32(res, false); 428 f32[0] = res; 429 } 430 test(refuseLoop); 431 432 function acceptLoop() { 433 // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773). 434 return; 435 436 var res = f32[0], 437 n = 10; 438 while (n--) { 439 var sum = res + 1; 440 res = Math.fround(sum); 441 assertFloat32(sum, true); 442 } 443 assertFloat32(res, true); 444 f32[0] = res; 445 } 446 test(acceptLoop); 447 448 function alternateCond(n) { 449 var x = f32[0]; 450 if (n > 0) { 451 var s1 = x + 1; 452 f32[0] = s1; 453 assertFloat32(s1, true); 454 } else { 455 var s2 = x + 1; 456 f64[0] = s2; // non consumer 457 assertFloat32(s2, false); 458 } 459 } 460 (function() { 461 f32[0] = 0; 462 for (var n = 110; n; n--) { 463 alternateCond(n % 2); 464 } 465 })(); 466 467 function phiTest(n) { 468 // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773). 469 return; 470 471 var x = (f32[0]); 472 var y = n; 473 if (n > 0) { 474 x = x + 2; 475 assertFloat32(x, true); 476 } else { 477 if (n < -10) { 478 x = Math.fround(Math.sqrt(y)); 479 assertFloat32(x, true); 480 } else { 481 x = x - 1; 482 assertFloat32(x, true); 483 } 484 } 485 assertFloat32(x, true); 486 f32[0] = x; 487 } 488 (function() { 489 f32[0] = 0; 490 for (var n = 100; n; n--) { 491 phiTest( ((n % 3) - 1) * 15 ); 492 } 493 })(); 494 495 function mixedPhiTest(n) { 496 // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773). 497 return; 498 499 var x = (f32[0]); 500 var y = n; 501 if (n > 0) { 502 x = x + 2; // non consumer because of (1) 503 assertFloat32(x, false); 504 } else { 505 if (n < -10) { 506 x = Math.fround(Math.sqrt(y)); // new producer 507 assertFloat32(x, true); 508 } else { 509 x = x - 1; // non consumer because of (1) 510 assertFloat32(x, false); 511 } 512 } 513 assertFloat32(x, false); 514 x = x + 1; // (1) non consumer 515 f32[0] = x; 516 } 517 (function() { 518 f32[0] = 0; 519 for (var n = 100; n; n--) { 520 mixedPhiTest( ((n % 3) - 1) * 15 ); 521 } 522 })(); 523 524 function phiTest2(n) { 525 // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773). 526 return; 527 528 var x = f32[0]; 529 while (n >= 0) { 530 x = Math.fround(Math.fround(x) + 1); 531 assertFloat32(x, true); 532 if (n < 10) { 533 x = f32[0] + 1; 534 assertFloat32(x, true); 535 } 536 n = n - 1; 537 } 538 } 539 (function(){ 540 f32[0] = 0; 541 for (var n = 100; n > 10; n--) { 542 phiTest2(n); 543 } 544 })();