1/*
2 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "testb3.h"
28
29#if ENABLE(B3_JIT)
30
31void testBitOrBitOrArgImmImm32(int a, int b, int c)
32{
33 Procedure proc;
34 BasicBlock* root = proc.addBlock();
35 Value* innerBitOr = root->appendNew<Value>(
36 proc, BitOr, Origin(),
37 root->appendNew<Value>(
38 proc, Trunc, Origin(),
39 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
40 root->appendNew<Const32Value>(proc, Origin(), b));
41 root->appendNewControlValue(
42 proc, Return, Origin(),
43 root->appendNew<Value>(
44 proc, BitOr, Origin(),
45 innerBitOr,
46 root->appendNew<Const32Value>(proc, Origin(), c)));
47
48 CHECK(compileAndRun<int>(proc, a) == ((a | b) | c));
49}
50
51void testBitOrImmBitOrArgImm32(int a, int b, int c)
52{
53 Procedure proc;
54 BasicBlock* root = proc.addBlock();
55 Value* innerBitOr = root->appendNew<Value>(
56 proc, BitOr, Origin(),
57 root->appendNew<Value>(
58 proc, Trunc, Origin(),
59 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
60 root->appendNew<Const32Value>(proc, Origin(), c));
61 root->appendNewControlValue(
62 proc, Return, Origin(),
63 root->appendNew<Value>(
64 proc, BitOr, Origin(),
65 root->appendNew<Const32Value>(proc, Origin(), a),
66 innerBitOr));
67
68 CHECK(compileAndRun<int>(proc, b) == (a | (b | c)));
69}
70
71double bitOrDouble(double a, double b)
72{
73 return bitwise_cast<double>(bitwise_cast<uint64_t>(a) | bitwise_cast<uint64_t>(b));
74}
75
76void testBitOrArgDouble(double a)
77{
78 Procedure proc;
79 BasicBlock* root = proc.addBlock();
80 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
81 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument);
82 root->appendNewControlValue(proc, Return, Origin(), result);
83
84 CHECK(isIdentical(compileAndRun<double>(proc, a), bitOrDouble(a, a)));
85}
86
87void testBitOrArgsDouble(double a, double b)
88{
89 Procedure proc;
90 BasicBlock* root = proc.addBlock();
91 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
92 Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
93 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
94 root->appendNewControlValue(proc, Return, Origin(), result);
95
96 CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
97}
98
99void testBitOrArgImmDouble(double a, double b)
100{
101 Procedure proc;
102 BasicBlock* root = proc.addBlock();
103 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
104 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
105 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
106 root->appendNewControlValue(proc, Return, Origin(), result);
107
108 CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
109}
110
111void testBitOrImmsDouble(double a, double b)
112{
113 Procedure proc;
114 BasicBlock* root = proc.addBlock();
115 Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
116 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
117 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
118 root->appendNewControlValue(proc, Return, Origin(), result);
119
120 CHECK(isIdentical(compileAndRun<double>(proc), bitOrDouble(a, b)));
121}
122
123float bitOrFloat(float a, float b)
124{
125 return bitwise_cast<float>(bitwise_cast<uint32_t>(a) | bitwise_cast<uint32_t>(b));
126}
127
128void testBitOrArgFloat(float a)
129{
130 Procedure proc;
131 BasicBlock* root = proc.addBlock();
132 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
133 root->appendNew<Value>(proc, Trunc, Origin(),
134 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
135 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument);
136 root->appendNewControlValue(proc, Return, Origin(), result);
137
138 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitOrFloat(a, a)));
139}
140
141void testBitOrArgsFloat(float a, float b)
142{
143 Procedure proc;
144 BasicBlock* root = proc.addBlock();
145 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
146 root->appendNew<Value>(proc, Trunc, Origin(),
147 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
148 Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
149 root->appendNew<Value>(proc, Trunc, Origin(),
150 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
151 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
152 root->appendNewControlValue(proc, Return, Origin(), result);
153
154 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
155}
156
157void testBitOrArgImmFloat(float a, float b)
158{
159 Procedure proc;
160 BasicBlock* root = proc.addBlock();
161 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
162 root->appendNew<Value>(proc, Trunc, Origin(),
163 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
164 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
165 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
166 root->appendNewControlValue(proc, Return, Origin(), result);
167
168 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
169}
170
171void testBitOrImmsFloat(float a, float b)
172{
173 Procedure proc;
174 BasicBlock* root = proc.addBlock();
175 Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
176 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
177 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
178 root->appendNewControlValue(proc, Return, Origin(), result);
179
180 CHECK(isIdentical(compileAndRun<float>(proc), bitOrFloat(a, b)));
181}
182
183void testBitOrArgsFloatWithUselessDoubleConversion(float a, float b)
184{
185 Procedure proc;
186 BasicBlock* root = proc.addBlock();
187 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
188 root->appendNew<Value>(proc, Trunc, Origin(),
189 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
190 Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
191 root->appendNew<Value>(proc, Trunc, Origin(),
192 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
193 Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
194 Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
195 Value* doubleResult = root->appendNew<Value>(proc, BitOr, Origin(), argumentAasDouble, argumentBasDouble);
196 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
197 root->appendNewControlValue(proc, Return, Origin(), floatResult);
198
199 double doubleA = a;
200 double doubleB = b;
201 float expected = static_cast<float>(bitOrDouble(doubleA, doubleB));
202 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
203}
204
205void testBitXorArgs(int64_t a, int64_t b)
206{
207 Procedure proc;
208 BasicBlock* root = proc.addBlock();
209 root->appendNewControlValue(
210 proc, Return, Origin(),
211 root->appendNew<Value>(
212 proc, BitXor, Origin(),
213 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
214 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
215
216 CHECK(compileAndRun<int64_t>(proc, a, b) == (a ^ b));
217}
218
219void testBitXorSameArg(int64_t a)
220{
221 Procedure proc;
222 BasicBlock* root = proc.addBlock();
223 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
224 root->appendNewControlValue(
225 proc, Return, Origin(),
226 root->appendNew<Value>(
227 proc, BitXor, Origin(),
228 argument,
229 argument));
230
231 CHECK(!compileAndRun<int64_t>(proc, a));
232}
233
234void testBitXorAndAndArgs(int64_t a, int64_t b, int64_t c)
235{
236 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
237 // ((a & b) ^ (a & c))
238 // ((a & b) ^ (c & a))
239 // ((b & a) ^ (a & c))
240 // ((b & a) ^ (c & a))
241 for (int i = 0; i < 4; ++i) {
242 Procedure proc;
243 BasicBlock* root = proc.addBlock();
244 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
245 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
246 Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
247 Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
248 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
249 Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
250 : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
251 root->appendNewControlValue(
252 proc, Return, Origin(),
253 root->appendNew<Value>(
254 proc, BitXor, Origin(),
255 andAB,
256 andAC));
257
258 CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a & b) ^ (a & c)));
259 }
260}
261
262void testBitXorAndAndArgs32(int32_t a, int32_t b, int32_t c)
263{
264 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
265 // ((a & b) ^ (a & c))
266 // ((a & b) ^ (c & a))
267 // ((b & a) ^ (a & c))
268 // ((b & a) ^ (c & a))
269 for (int i = 0; i < 4; ++i) {
270 Procedure proc;
271 BasicBlock* root = proc.addBlock();
272 Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
273 Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
274 Value* argC = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
275 Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
276 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
277 Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
278 : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
279 root->appendNewControlValue(
280 proc, Return, Origin(),
281 root->appendNew<Value>(
282 proc, BitXor, Origin(),
283 andAB,
284 andAC));
285
286 CHECK_EQ(compileAndRun<int32_t>(proc, a, b, c), ((a & b) ^ (a & c)));
287 }
288}
289
290void testBitXorAndSameArgs(int64_t a, int64_t b)
291{
292 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
293 // ((a & b) ^ a)
294 // ((b & a) ^ a)
295 // (a ^ (a & b))
296 // (a ^ (b & a))
297 for (int i = 0; i < 4; ++i) {
298 Procedure proc;
299 BasicBlock* root = proc.addBlock();
300 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
301 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
302 Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
303 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
304 Value* result = i & 2 ? root->appendNew<Value>(proc, BitXor, Origin(), andAB, argA)
305 : root->appendNew<Value>(proc, BitXor, Origin(), argA, andAB);
306 root->appendNewControlValue(proc, Return, Origin(), result);
307
308 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a & b) ^ a));
309 }
310}
311
312void testBitXorAndSameArgs32(int32_t a, int32_t b)
313{
314 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
315 // ((a & b) ^ a)
316 // ((b & a) ^ a)
317 // (a ^ (a & b))
318 // (a ^ (b & a))
319 for (int i = 0; i < 4; ++i) {
320 Procedure proc;
321 BasicBlock* root = proc.addBlock();
322 Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
323 Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
324 Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
325 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
326 Value* result = i & 2 ? root->appendNew<Value>(proc, BitXor, Origin(), andAB, argA)
327 : root->appendNew<Value>(proc, BitXor, Origin(), argA, andAB);
328 root->appendNewControlValue(proc, Return, Origin(), result);
329
330 CHECK_EQ(compileAndRun<int32_t>(proc, a, b), ((a & b) ^ a));
331 }
332}
333
334void testBitXorImms(int64_t a, int64_t b)
335{
336 Procedure proc;
337 BasicBlock* root = proc.addBlock();
338 root->appendNewControlValue(
339 proc, Return, Origin(),
340 root->appendNew<Value>(
341 proc, BitXor, Origin(),
342 root->appendNew<Const64Value>(proc, Origin(), a),
343 root->appendNew<Const64Value>(proc, Origin(), b)));
344
345 CHECK(compileAndRun<int64_t>(proc) == (a ^ b));
346}
347
348void testBitXorArgImm(int64_t a, int64_t b)
349{
350 Procedure proc;
351 BasicBlock* root = proc.addBlock();
352 root->appendNewControlValue(
353 proc, Return, Origin(),
354 root->appendNew<Value>(
355 proc, BitXor, Origin(),
356 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
357 root->appendNew<Const64Value>(proc, Origin(), b)));
358
359 CHECK(compileAndRun<int64_t>(proc, a) == (a ^ b));
360}
361
362void testBitXorImmArg(int64_t a, int64_t b)
363{
364 Procedure proc;
365 BasicBlock* root = proc.addBlock();
366 root->appendNewControlValue(
367 proc, Return, Origin(),
368 root->appendNew<Value>(
369 proc, BitXor, Origin(),
370 root->appendNew<Const64Value>(proc, Origin(), a),
371 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
372
373 CHECK(compileAndRun<int64_t>(proc, b) == (a ^ b));
374}
375
376void testBitXorBitXorArgImmImm(int64_t a, int64_t b, int64_t c)
377{
378 Procedure proc;
379 BasicBlock* root = proc.addBlock();
380 Value* innerBitXor = root->appendNew<Value>(
381 proc, BitXor, Origin(),
382 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
383 root->appendNew<Const64Value>(proc, Origin(), b));
384 root->appendNewControlValue(
385 proc, Return, Origin(),
386 root->appendNew<Value>(
387 proc, BitXor, Origin(),
388 innerBitXor,
389 root->appendNew<Const64Value>(proc, Origin(), c)));
390
391 CHECK(compileAndRun<int64_t>(proc, a) == ((a ^ b) ^ c));
392}
393
394void testBitXorImmBitXorArgImm(int64_t a, int64_t b, int64_t c)
395{
396 Procedure proc;
397 BasicBlock* root = proc.addBlock();
398 Value* innerBitXor = root->appendNew<Value>(
399 proc, BitXor, Origin(),
400 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
401 root->appendNew<Const64Value>(proc, Origin(), c));
402 root->appendNewControlValue(
403 proc, Return, Origin(),
404 root->appendNew<Value>(
405 proc, BitXor, Origin(),
406 root->appendNew<Const64Value>(proc, Origin(), a),
407 innerBitXor));
408
409 CHECK(compileAndRun<int64_t>(proc, b) == (a ^ (b ^ c)));
410}
411
412void testBitXorArgs32(int a, int b)
413{
414 Procedure proc;
415 BasicBlock* root = proc.addBlock();
416 root->appendNewControlValue(
417 proc, Return, Origin(),
418 root->appendNew<Value>(
419 proc, BitXor, Origin(),
420 root->appendNew<Value>(
421 proc, Trunc, Origin(),
422 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
423 root->appendNew<Value>(
424 proc, Trunc, Origin(),
425 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
426
427 CHECK(compileAndRun<int>(proc, a, b) == (a ^ b));
428}
429
430void testBitXorSameArg32(int a)
431{
432 Procedure proc;
433 BasicBlock* root = proc.addBlock();
434 Value* argument = root->appendNew<Value>(
435 proc, Trunc, Origin(),
436 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
437 root->appendNewControlValue(
438 proc, Return, Origin(),
439 root->appendNew<Value>(
440 proc, BitXor, Origin(),
441 argument,
442 argument));
443
444 CHECK(!compileAndRun<int>(proc, a));
445}
446
447void testBitXorImms32(int a, int b)
448{
449 Procedure proc;
450 BasicBlock* root = proc.addBlock();
451 root->appendNewControlValue(
452 proc, Return, Origin(),
453 root->appendNew<Value>(
454 proc, BitXor, Origin(),
455 root->appendNew<Const32Value>(proc, Origin(), a),
456 root->appendNew<Const32Value>(proc, Origin(), b)));
457
458 CHECK(compileAndRun<int>(proc) == (a ^ b));
459}
460
461void testBitXorArgImm32(int a, int b)
462{
463 Procedure proc;
464 BasicBlock* root = proc.addBlock();
465 root->appendNewControlValue(
466 proc, Return, Origin(),
467 root->appendNew<Value>(
468 proc, BitXor, Origin(),
469 root->appendNew<Value>(
470 proc, Trunc, Origin(),
471 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
472 root->appendNew<Const32Value>(proc, Origin(), b)));
473
474 CHECK(compileAndRun<int>(proc, a) == (a ^ b));
475}
476
477void testBitXorImmArg32(int a, int b)
478{
479 Procedure proc;
480 BasicBlock* root = proc.addBlock();
481 root->appendNewControlValue(
482 proc, Return, Origin(),
483 root->appendNew<Value>(
484 proc, BitXor, Origin(),
485 root->appendNew<Const32Value>(proc, Origin(), a),
486 root->appendNew<Value>(
487 proc, Trunc, Origin(),
488 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
489
490 CHECK(compileAndRun<int>(proc, b) == (a ^ b));
491}
492
493void testBitXorBitXorArgImmImm32(int a, int b, int c)
494{
495 Procedure proc;
496 BasicBlock* root = proc.addBlock();
497 Value* innerBitXor = root->appendNew<Value>(
498 proc, BitXor, Origin(),
499 root->appendNew<Value>(
500 proc, Trunc, Origin(),
501 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
502 root->appendNew<Const32Value>(proc, Origin(), b));
503 root->appendNewControlValue(
504 proc, Return, Origin(),
505 root->appendNew<Value>(
506 proc, BitXor, Origin(),
507 innerBitXor,
508 root->appendNew<Const32Value>(proc, Origin(), c)));
509
510 CHECK(compileAndRun<int>(proc, a) == ((a ^ b) ^ c));
511}
512
513void testBitXorImmBitXorArgImm32(int a, int b, int c)
514{
515 Procedure proc;
516 BasicBlock* root = proc.addBlock();
517 Value* innerBitXor = root->appendNew<Value>(
518 proc, BitXor, Origin(),
519 root->appendNew<Value>(
520 proc, Trunc, Origin(),
521 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
522 root->appendNew<Const32Value>(proc, Origin(), c));
523 root->appendNewControlValue(
524 proc, Return, Origin(),
525 root->appendNew<Value>(
526 proc, BitXor, Origin(),
527 root->appendNew<Const32Value>(proc, Origin(), a),
528 innerBitXor));
529
530 CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c)));
531}
532
533void testBitNotArg(int64_t a)
534{
535 Procedure proc;
536 BasicBlock* root = proc.addBlock();
537 root->appendNewControlValue(
538 proc, Return, Origin(),
539 root->appendNew<Value>(
540 proc, BitXor, Origin(),
541 root->appendNew<Const64Value>(proc, Origin(), -1),
542 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
543
544 CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
545}
546
547void testBitNotImm(int64_t a)
548{
549 Procedure proc;
550 BasicBlock* root = proc.addBlock();
551 root->appendNewControlValue(
552 proc, Return, Origin(),
553 root->appendNew<Value>(
554 proc, BitXor, Origin(),
555 root->appendNew<Const64Value>(proc, Origin(), -1),
556 root->appendNew<Const64Value>(proc, Origin(), a)));
557
558 CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
559}
560
561void testBitNotMem(int64_t a)
562{
563 Procedure proc;
564 BasicBlock* root = proc.addBlock();
565 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
566 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
567 Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
568 root->appendNew<Const64Value>(proc, Origin(), -1),
569 load);
570 root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
571 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
572
573 int64_t input = a;
574 compileAndRun<int32_t>(proc, &input);
575 CHECK(isIdentical(input, static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
576}
577
578void testBitNotArg32(int32_t a)
579{
580 Procedure proc;
581 BasicBlock* root = proc.addBlock();
582 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
583 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
584 root->appendNewControlValue(
585 proc, Return, Origin(),
586 root->appendNew<Value>(proc, BitXor, Origin(),
587 root->appendNew<Const32Value>(proc, Origin(), -1),
588 argument));
589 CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
590}
591
592void testBitNotImm32(int32_t a)
593{
594 Procedure proc;
595 BasicBlock* root = proc.addBlock();
596 root->appendNewControlValue(
597 proc, Return, Origin(),
598 root->appendNew<Value>(
599 proc, BitXor, Origin(),
600 root->appendNew<Const32Value>(proc, Origin(), -1),
601 root->appendNew<Const32Value>(proc, Origin(), a)));
602
603 CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
604}
605
606void testBitNotMem32(int32_t a)
607{
608 Procedure proc;
609 BasicBlock* root = proc.addBlock();
610 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
611 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
612 Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
613 root->appendNew<Const32Value>(proc, Origin(), -1),
614 load);
615 root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
616 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
617
618 int32_t input = a;
619 compileAndRun<int32_t>(proc, &input);
620 CHECK(isIdentical(input, static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
621}
622
623void testNotOnBooleanAndBranch32(int64_t a, int64_t b)
624{
625 Procedure proc;
626 BasicBlock* root = proc.addBlock();
627 BasicBlock* thenCase = proc.addBlock();
628 BasicBlock* elseCase = proc.addBlock();
629
630 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
631 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
632 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
633 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
634 Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
635 Value* argsAreNotEqual = root->appendNew<Value>(proc, BitXor, Origin(),
636 root->appendNew<Const32Value>(proc, Origin(), 1),
637 argsAreEqual);
638
639 root->appendNewControlValue(
640 proc, Branch, Origin(),
641 argsAreNotEqual,
642 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
643
644 thenCase->appendNewControlValue(
645 proc, Return, Origin(),
646 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
647
648 elseCase->appendNewControlValue(
649 proc, Return, Origin(),
650 elseCase->appendNew<Const32Value>(proc, Origin(), -42));
651
652 int32_t expectedValue = (a != b) ? 42 : -42;
653 CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue);
654}
655
656void testBitNotOnBooleanAndBranch32(int64_t a, int64_t b)
657{
658 Procedure proc;
659 BasicBlock* root = proc.addBlock();
660 BasicBlock* thenCase = proc.addBlock();
661 BasicBlock* elseCase = proc.addBlock();
662
663 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
664 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
665 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
666 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
667 Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
668 Value* bitNotArgsAreEqual = root->appendNew<Value>(proc, BitXor, Origin(),
669 root->appendNew<Const32Value>(proc, Origin(), -1),
670 argsAreEqual);
671
672 root->appendNewControlValue(proc, Branch, Origin(),
673 bitNotArgsAreEqual, FrequentedBlock(thenCase), FrequentedBlock(elseCase));
674
675 thenCase->appendNewControlValue(proc, Return, Origin(),
676 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
677
678 elseCase->appendNewControlValue(proc, Return, Origin(),
679 elseCase->appendNew<Const32Value>(proc, Origin(), -42));
680
681 static constexpr int32_t expectedValue = 42;
682 CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue);
683}
684
685void testShlArgs(int64_t a, int64_t b)
686{
687 Procedure proc;
688 BasicBlock* root = proc.addBlock();
689 root->appendNewControlValue(
690 proc, Return, Origin(),
691 root->appendNew<Value>(
692 proc, Shl, Origin(),
693 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
694 root->appendNew<Value>(
695 proc, Trunc, Origin(),
696 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
697
698 CHECK(compileAndRun<int64_t>(proc, a, b) == (a << b));
699}
700
701void testShlImms(int64_t a, int64_t b)
702{
703 Procedure proc;
704 BasicBlock* root = proc.addBlock();
705 root->appendNewControlValue(
706 proc, Return, Origin(),
707 root->appendNew<Value>(
708 proc, Shl, Origin(),
709 root->appendNew<Const64Value>(proc, Origin(), a),
710 root->appendNew<Const32Value>(proc, Origin(), b)));
711
712 b = b & 0x3f; // to avoid undefined behaviour below
713 CHECK(compileAndRun<int64_t>(proc) == (a << b));
714}
715
716void testShlArgImm(int64_t a, int64_t b)
717{
718 Procedure proc;
719 BasicBlock* root = proc.addBlock();
720 root->appendNewControlValue(
721 proc, Return, Origin(),
722 root->appendNew<Value>(
723 proc, Shl, Origin(),
724 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
725 root->appendNew<Const32Value>(proc, Origin(), b)));
726
727 b = b & 0x3f; // to avoid undefined behaviour below
728 CHECK(compileAndRun<int64_t>(proc, a) == (a << b));
729}
730
731void testShlSShrArgImm(int64_t a, int64_t b)
732{
733 Procedure proc;
734 BasicBlock* root = proc.addBlock();
735 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
736 Value* constB = root->appendNew<Const32Value>(proc, Origin(), b);
737 Value* innerShift = root->appendNew<Value>(proc, SShr, Origin(), argA, constB);
738 root->appendNewControlValue(
739 proc, Return, Origin(),
740 root->appendNew<Value>(
741 proc, Shl, Origin(),
742 innerShift,
743 constB));
744
745 b = b & 0x3f; // to avoid undefined behaviour below
746 CHECK(compileAndRun<int64_t>(proc, a) == ((a >> b) << b));
747}
748
749void testShlArg32(int32_t a)
750{
751 Procedure proc;
752 BasicBlock* root = proc.addBlock();
753 Value* value = root->appendNew<Value>(
754 proc, Trunc, Origin(),
755 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
756 root->appendNewControlValue(
757 proc, Return, Origin(),
758 root->appendNew<Value>(proc, Shl, Origin(), value, value));
759
760 CHECK(compileAndRun<int32_t>(proc, a) == (a << a));
761}
762
763void testShlArgs32(int32_t a, int32_t b)
764{
765 Procedure proc;
766 BasicBlock* root = proc.addBlock();
767 root->appendNewControlValue(
768 proc, Return, Origin(),
769 root->appendNew<Value>(
770 proc, Shl, Origin(),
771 root->appendNew<Value>(
772 proc, Trunc, Origin(),
773 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
774 root->appendNew<Value>(
775 proc, Trunc, Origin(),
776 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
777
778 CHECK(compileAndRun<int32_t>(proc, a, b) == (a << b));
779}
780
781void testShlImms32(int32_t a, int32_t b)
782{
783 Procedure proc;
784 BasicBlock* root = proc.addBlock();
785 root->appendNewControlValue(
786 proc, Return, Origin(),
787 root->appendNew<Value>(
788 proc, Shl, Origin(),
789 root->appendNew<Const32Value>(proc, Origin(), a),
790 root->appendNew<Const32Value>(proc, Origin(), b)));
791
792 b = b & 0x1f; // to avoid undefined behaviour below
793 CHECK(compileAndRun<int32_t>(proc) == (a << b));
794}
795
796void testShlArgImm32(int32_t a, int32_t b)
797{
798 Procedure proc;
799 BasicBlock* root = proc.addBlock();
800 root->appendNewControlValue(
801 proc, Return, Origin(),
802 root->appendNew<Value>(
803 proc, Shl, Origin(),
804 root->appendNew<Value>(
805 proc, Trunc, Origin(),
806 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
807 root->appendNew<Const32Value>(proc, Origin(), b)));
808
809 b = b & 0x1f; // to avoid undefined behaviour below
810 CHECK(compileAndRun<int32_t>(proc, a) == (a << b));
811}
812
813void testShlZShrArgImm32(int32_t a, int32_t b)
814{
815 Procedure proc;
816 BasicBlock* root = proc.addBlock();
817 Value* argA = root->appendNew<Value>(
818 proc, Trunc, Origin(),
819 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
820 Value* constB = root->appendNew<Const32Value>(proc, Origin(), b);
821 Value* innerShift = root->appendNew<Value>(proc, ZShr, Origin(), argA, constB);
822 root->appendNewControlValue(
823 proc, Return, Origin(),
824 root->appendNew<Value>(
825 proc, Shl, Origin(),
826 innerShift,
827 constB));
828
829 b = b & 0x1f; // to avoid undefined behaviour below
830 CHECK(compileAndRun<int32_t>(proc, a) == static_cast<int32_t>((static_cast<uint32_t>(a) >> b) << b));
831}
832
833static void testSShrArgs(int64_t a, int64_t b)
834{
835 Procedure proc;
836 BasicBlock* root = proc.addBlock();
837 root->appendNewControlValue(
838 proc, Return, Origin(),
839 root->appendNew<Value>(
840 proc, SShr, Origin(),
841 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
842 root->appendNew<Value>(
843 proc, Trunc, Origin(),
844 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
845
846 CHECK(compileAndRun<int64_t>(proc, a, b) == (a >> b));
847}
848
849static void testSShrImms(int64_t a, int64_t b)
850{
851 Procedure proc;
852 BasicBlock* root = proc.addBlock();
853 root->appendNewControlValue(
854 proc, Return, Origin(),
855 root->appendNew<Value>(
856 proc, SShr, Origin(),
857 root->appendNew<Const64Value>(proc, Origin(), a),
858 root->appendNew<Const32Value>(proc, Origin(), b)));
859
860 CHECK(compileAndRun<int64_t>(proc) == (a >> b));
861}
862
863static void testSShrArgImm(int64_t a, int64_t b)
864{
865 Procedure proc;
866 BasicBlock* root = proc.addBlock();
867 root->appendNewControlValue(
868 proc, Return, Origin(),
869 root->appendNew<Value>(
870 proc, SShr, Origin(),
871 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
872 root->appendNew<Const32Value>(proc, Origin(), b)));
873
874 CHECK(compileAndRun<int64_t>(proc, a) == (a >> b));
875}
876
877static void testSShrArg32(int32_t a)
878{
879 Procedure proc;
880 BasicBlock* root = proc.addBlock();
881 Value* value = root->appendNew<Value>(
882 proc, Trunc, Origin(),
883 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
884 root->appendNewControlValue(
885 proc, Return, Origin(),
886 root->appendNew<Value>(proc, SShr, Origin(), value, value));
887
888 CHECK(compileAndRun<int32_t>(proc, a) == (a >> (a & 31)));
889}
890
891static void testSShrArgs32(int32_t a, int32_t b)
892{
893 Procedure proc;
894 BasicBlock* root = proc.addBlock();
895 root->appendNewControlValue(
896 proc, Return, Origin(),
897 root->appendNew<Value>(
898 proc, SShr, Origin(),
899 root->appendNew<Value>(
900 proc, Trunc, Origin(),
901 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
902 root->appendNew<Value>(
903 proc, Trunc, Origin(),
904 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
905
906 CHECK(compileAndRun<int32_t>(proc, a, b) == (a >> b));
907}
908
909static void testSShrImms32(int32_t a, int32_t b)
910{
911 Procedure proc;
912 BasicBlock* root = proc.addBlock();
913 root->appendNewControlValue(
914 proc, Return, Origin(),
915 root->appendNew<Value>(
916 proc, SShr, Origin(),
917 root->appendNew<Const32Value>(proc, Origin(), a),
918 root->appendNew<Const32Value>(proc, Origin(), b)));
919
920 CHECK(compileAndRun<int32_t>(proc) == (a >> b));
921}
922
923static void testSShrArgImm32(int32_t a, int32_t b)
924{
925 Procedure proc;
926 BasicBlock* root = proc.addBlock();
927 root->appendNewControlValue(
928 proc, Return, Origin(),
929 root->appendNew<Value>(
930 proc, SShr, Origin(),
931 root->appendNew<Value>(
932 proc, Trunc, Origin(),
933 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
934 root->appendNew<Const32Value>(proc, Origin(), b)));
935
936 CHECK(compileAndRun<int32_t>(proc, a) == (a >> b));
937}
938
939static void testZShrArgs(uint64_t a, uint64_t b)
940{
941 Procedure proc;
942 BasicBlock* root = proc.addBlock();
943 root->appendNewControlValue(
944 proc, Return, Origin(),
945 root->appendNew<Value>(
946 proc, ZShr, Origin(),
947 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
948 root->appendNew<Value>(
949 proc, Trunc, Origin(),
950 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
951
952 CHECK(compileAndRun<uint64_t>(proc, a, b) == (a >> b));
953}
954
955static void testZShrImms(uint64_t a, uint64_t b)
956{
957 Procedure proc;
958 BasicBlock* root = proc.addBlock();
959 root->appendNewControlValue(
960 proc, Return, Origin(),
961 root->appendNew<Value>(
962 proc, ZShr, Origin(),
963 root->appendNew<Const64Value>(proc, Origin(), a),
964 root->appendNew<Const32Value>(proc, Origin(), b)));
965
966 CHECK(compileAndRun<uint64_t>(proc) == (a >> b));
967}
968
969static void testZShrArgImm(uint64_t a, uint64_t b)
970{
971 Procedure proc;
972 BasicBlock* root = proc.addBlock();
973 root->appendNewControlValue(
974 proc, Return, Origin(),
975 root->appendNew<Value>(
976 proc, ZShr, Origin(),
977 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
978 root->appendNew<Const32Value>(proc, Origin(), b)));
979
980 CHECK(compileAndRun<uint64_t>(proc, a) == (a >> b));
981}
982
983static void testZShrArg32(uint32_t a)
984{
985 Procedure proc;
986 BasicBlock* root = proc.addBlock();
987 Value* value = root->appendNew<Value>(
988 proc, Trunc, Origin(),
989 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
990 root->appendNewControlValue(
991 proc, Return, Origin(),
992 root->appendNew<Value>(proc, ZShr, Origin(), value, value));
993
994 CHECK(compileAndRun<uint32_t>(proc, a) == (a >> (a & 31)));
995}
996
997static void testZShrArgs32(uint32_t a, uint32_t b)
998{
999 Procedure proc;
1000 BasicBlock* root = proc.addBlock();
1001 root->appendNewControlValue(
1002 proc, Return, Origin(),
1003 root->appendNew<Value>(
1004 proc, ZShr, Origin(),
1005 root->appendNew<Value>(
1006 proc, Trunc, Origin(),
1007 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1008 root->appendNew<Value>(
1009 proc, Trunc, Origin(),
1010 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1011
1012 CHECK(compileAndRun<uint32_t>(proc, a, b) == (a >> b));
1013}
1014
1015static void testZShrImms32(uint32_t a, uint32_t b)
1016{
1017 Procedure proc;
1018 BasicBlock* root = proc.addBlock();
1019 root->appendNewControlValue(
1020 proc, Return, Origin(),
1021 root->appendNew<Value>(
1022 proc, ZShr, Origin(),
1023 root->appendNew<Const32Value>(proc, Origin(), a),
1024 root->appendNew<Const32Value>(proc, Origin(), b)));
1025
1026 CHECK(compileAndRun<uint32_t>(proc) == (a >> b));
1027}
1028
1029static void testZShrArgImm32(uint32_t a, uint32_t b)
1030{
1031 Procedure proc;
1032 BasicBlock* root = proc.addBlock();
1033 root->appendNewControlValue(
1034 proc, Return, Origin(),
1035 root->appendNew<Value>(
1036 proc, ZShr, Origin(),
1037 root->appendNew<Value>(
1038 proc, Trunc, Origin(),
1039 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1040 root->appendNew<Const32Value>(proc, Origin(), b)));
1041
1042 CHECK(compileAndRun<uint32_t>(proc, a) == (a >> b));
1043}
1044
1045template<typename IntegerType>
1046static unsigned countLeadingZero(IntegerType value)
1047{
1048 unsigned bitCount = sizeof(IntegerType) * 8;
1049 if (!value)
1050 return bitCount;
1051
1052 unsigned counter = 0;
1053 while (!(static_cast<uint64_t>(value) & (1l << (bitCount - 1)))) {
1054 value <<= 1;
1055 ++counter;
1056 }
1057 return counter;
1058}
1059
1060void testClzArg64(int64_t a)
1061{
1062 Procedure proc;
1063 BasicBlock* root = proc.addBlock();
1064 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1065 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
1066 root->appendNewControlValue(proc, Return, Origin(), clzValue);
1067 CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
1068}
1069
1070void testClzMem64(int64_t a)
1071{
1072 Procedure proc;
1073 BasicBlock* root = proc.addBlock();
1074 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1075 MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1076 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
1077 root->appendNewControlValue(proc, Return, Origin(), clzValue);
1078 CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
1079}
1080
1081void testClzArg32(int32_t a)
1082{
1083 Procedure proc;
1084 BasicBlock* root = proc.addBlock();
1085 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
1086 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1087 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
1088 root->appendNewControlValue(proc, Return, Origin(), clzValue);
1089 CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
1090}
1091
1092void testClzMem32(int32_t a)
1093{
1094 Procedure proc;
1095 BasicBlock* root = proc.addBlock();
1096 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1097 MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
1098 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
1099 root->appendNewControlValue(proc, Return, Origin(), clzValue);
1100 CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
1101}
1102
1103void testAbsArg(double a)
1104{
1105 Procedure proc;
1106 BasicBlock* root = proc.addBlock();
1107 root->appendNewControlValue(
1108 proc, Return, Origin(),
1109 root->appendNew<Value>(
1110 proc, Abs, Origin(),
1111 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
1112
1113 CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a)));
1114}
1115
1116void testAbsImm(double a)
1117{
1118 Procedure proc;
1119 BasicBlock* root = proc.addBlock();
1120 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1121 root->appendNewControlValue(
1122 proc, Return, Origin(),
1123 root->appendNew<Value>(proc, Abs, Origin(), argument));
1124
1125 CHECK(isIdentical(compileAndRun<double>(proc), fabs(a)));
1126}
1127
1128void testAbsMem(double a)
1129{
1130 Procedure proc;
1131 BasicBlock* root = proc.addBlock();
1132 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1133 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
1134 root->appendNewControlValue(
1135 proc, Return, Origin(),
1136 root->appendNew<Value>(proc, Abs, Origin(), loadDouble));
1137
1138 CHECK(isIdentical(compileAndRun<double>(proc, &a), fabs(a)));
1139}
1140
1141void testAbsAbsArg(double a)
1142{
1143 Procedure proc;
1144 BasicBlock* root = proc.addBlock();
1145 Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(),
1146 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1147 Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
1148 root->appendNewControlValue(proc, Return, Origin(), secondAbs);
1149
1150 CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(fabs(a))));
1151}
1152
1153void testAbsNegArg(double a)
1154{
1155 Procedure proc;
1156 BasicBlock* root = proc.addBlock();
1157 Value* neg = root->appendNew<Value>(proc, Neg, Origin(),
1158 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1159 Value* abs = root->appendNew<Value>(proc, Abs, Origin(), neg);
1160 root->appendNewControlValue(proc, Return, Origin(), abs);
1161
1162 CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(- a)));
1163}
1164
1165void testAbsBitwiseCastArg(double a)
1166{
1167 Procedure proc;
1168 BasicBlock* root = proc.addBlock();
1169 Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1170 Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
1171 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
1172 root->appendNewControlValue(proc, Return, Origin(), absValue);
1173
1174 CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int64_t>(a)), fabs(a)));
1175}
1176
1177void testBitwiseCastAbsBitwiseCastArg(double a)
1178{
1179 Procedure proc;
1180 BasicBlock* root = proc.addBlock();
1181 Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1182 Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
1183 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
1184 Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
1185
1186 root->appendNewControlValue(proc, Return, Origin(), resultAsInt64);
1187
1188 int64_t expectedResult = bitwise_cast<int64_t>(fabs(a));
1189 CHECK(isIdentical(compileAndRun<int64_t>(proc, bitwise_cast<int64_t>(a)), expectedResult));
1190}
1191
1192void testAbsArg(float a)
1193{
1194 Procedure proc;
1195 BasicBlock* root = proc.addBlock();
1196 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1197 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1198 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1199 Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
1200 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1201 root->appendNewControlValue(proc, Return, Origin(), result32);
1202
1203 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
1204}
1205
1206void testAbsImm(float a)
1207{
1208 Procedure proc;
1209 BasicBlock* root = proc.addBlock();
1210 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1211 Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
1212 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1213 root->appendNewControlValue(proc, Return, Origin(), result32);
1214
1215 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
1216}
1217
1218void testAbsMem(float a)
1219{
1220 Procedure proc;
1221 BasicBlock* root = proc.addBlock();
1222 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1223 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
1224 Value* result = root->appendNew<Value>(proc, Abs, Origin(), loadFloat);
1225 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1226 root->appendNewControlValue(proc, Return, Origin(), result32);
1227
1228 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
1229}
1230
1231void testAbsAbsArg(float a)
1232{
1233 Procedure proc;
1234 BasicBlock* root = proc.addBlock();
1235 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1236 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1237 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1238 Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(), argument);
1239 Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
1240 root->appendNewControlValue(proc, Return, Origin(), secondAbs);
1241
1242 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(fabs(a)))));
1243}
1244
1245void testAbsNegArg(float a)
1246{
1247 Procedure proc;
1248 BasicBlock* root = proc.addBlock();
1249 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1250 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1251 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1252 Value* neg = root->appendNew<Value>(proc, Neg, Origin(), argument);
1253 Value* abs = root->appendNew<Value>(proc, Abs, Origin(), neg);
1254 root->appendNewControlValue(proc, Return, Origin(), abs);
1255
1256 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(- a))));
1257}
1258
1259void testAbsBitwiseCastArg(float a)
1260{
1261 Procedure proc;
1262 BasicBlock* root = proc.addBlock();
1263 Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1264 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1265 Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
1266 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
1267 root->appendNewControlValue(proc, Return, Origin(), absValue);
1268
1269 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a))));
1270}
1271
1272void testBitwiseCastAbsBitwiseCastArg(float a)
1273{
1274 Procedure proc;
1275 BasicBlock* root = proc.addBlock();
1276 Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1277 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1278 Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
1279 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
1280 Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
1281
1282 root->appendNewControlValue(proc, Return, Origin(), resultAsInt64);
1283
1284 int32_t expectedResult = bitwise_cast<int32_t>(static_cast<float>(fabs(a)));
1285 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), expectedResult));
1286}
1287
1288void testAbsArgWithUselessDoubleConversion(float a)
1289{
1290 Procedure proc;
1291 BasicBlock* root = proc.addBlock();
1292 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1293 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1294 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1295 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1296 Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
1297 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1298 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1299 root->appendNewControlValue(proc, Return, Origin(), result32);
1300
1301 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
1302}
1303
1304void testAbsArgWithEffectfulDoubleConversion(float a)
1305{
1306 Procedure proc;
1307 BasicBlock* root = proc.addBlock();
1308 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1309 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1310 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1311 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1312 Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
1313 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1314 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1315 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1316 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
1317 root->appendNewControlValue(proc, Return, Origin(), result32);
1318
1319 double effect = 0;
1320 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
1321 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
1322 CHECK(isIdentical(effect, static_cast<double>(fabs(a))));
1323}
1324
1325void testCeilArg(double a)
1326{
1327 Procedure proc;
1328 BasicBlock* root = proc.addBlock();
1329 root->appendNewControlValue(
1330 proc, Return, Origin(),
1331 root->appendNew<Value>(
1332 proc, Ceil, Origin(),
1333 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
1334
1335 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
1336}
1337
1338void testCeilImm(double a)
1339{
1340 Procedure proc;
1341 BasicBlock* root = proc.addBlock();
1342 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1343 root->appendNewControlValue(
1344 proc, Return, Origin(),
1345 root->appendNew<Value>(proc, Ceil, Origin(), argument));
1346
1347 CHECK(isIdentical(compileAndRun<double>(proc), ceil(a)));
1348}
1349
1350void testCeilMem(double a)
1351{
1352 Procedure proc;
1353 BasicBlock* root = proc.addBlock();
1354 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1355 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
1356 root->appendNewControlValue(
1357 proc, Return, Origin(),
1358 root->appendNew<Value>(proc, Ceil, Origin(), loadDouble));
1359
1360 CHECK(isIdentical(compileAndRun<double>(proc, &a), ceil(a)));
1361}
1362
1363void testCeilCeilArg(double a)
1364{
1365 Procedure proc;
1366 BasicBlock* root = proc.addBlock();
1367 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
1368 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1369 Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
1370 root->appendNewControlValue(proc, Return, Origin(), secondCeil);
1371
1372 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
1373}
1374
1375void testFloorCeilArg(double a)
1376{
1377 Procedure proc;
1378 BasicBlock* root = proc.addBlock();
1379 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
1380 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1381 Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil);
1382 root->appendNewControlValue(proc, Return, Origin(), wrappingFloor);
1383
1384 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
1385}
1386
1387void testCeilIToD64(int64_t a)
1388{
1389 Procedure proc;
1390 BasicBlock* root = proc.addBlock();
1391 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1392 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
1393
1394 root->appendNewControlValue(
1395 proc, Return, Origin(),
1396 root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
1397
1398 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
1399}
1400
1401void testCeilIToD32(int64_t a)
1402{
1403 Procedure proc;
1404 BasicBlock* root = proc.addBlock();
1405 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
1406 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1407 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
1408
1409 root->appendNewControlValue(
1410 proc, Return, Origin(),
1411 root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
1412
1413 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
1414}
1415
1416void testCeilArg(float a)
1417{
1418 Procedure proc;
1419 BasicBlock* root = proc.addBlock();
1420 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1421 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1422 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1423 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
1424 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1425 root->appendNewControlValue(proc, Return, Origin(), result32);
1426
1427 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
1428}
1429
1430void testCeilImm(float a)
1431{
1432 Procedure proc;
1433 BasicBlock* root = proc.addBlock();
1434 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1435 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
1436 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1437 root->appendNewControlValue(proc, Return, Origin(), result32);
1438
1439 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
1440}
1441
1442void testCeilMem(float a)
1443{
1444 Procedure proc;
1445 BasicBlock* root = proc.addBlock();
1446 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1447 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
1448 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), loadFloat);
1449 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1450 root->appendNewControlValue(proc, Return, Origin(), result32);
1451
1452 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(ceilf(a))));
1453}
1454
1455void testCeilCeilArg(float a)
1456{
1457 Procedure proc;
1458 BasicBlock* root = proc.addBlock();
1459 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1460 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1461 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1462 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
1463 Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
1464 root->appendNewControlValue(proc, Return, Origin(), secondCeil);
1465
1466 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
1467}
1468
1469void testFloorCeilArg(float a)
1470{
1471 Procedure proc;
1472 BasicBlock* root = proc.addBlock();
1473 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1474 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1475 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1476 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
1477 Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil);
1478 root->appendNewControlValue(proc, Return, Origin(), wrappingFloor);
1479
1480 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
1481}
1482
1483void testCeilArgWithUselessDoubleConversion(float a)
1484{
1485 Procedure proc;
1486 BasicBlock* root = proc.addBlock();
1487 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1488 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1489 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1490 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1491 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
1492 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1493 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1494 root->appendNewControlValue(proc, Return, Origin(), result32);
1495
1496 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
1497}
1498
1499void testCeilArgWithEffectfulDoubleConversion(float a)
1500{
1501 Procedure proc;
1502 BasicBlock* root = proc.addBlock();
1503 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1504 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1505 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1506 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1507 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
1508 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1509 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1510 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1511 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
1512 root->appendNewControlValue(proc, Return, Origin(), result32);
1513
1514 double effect = 0;
1515 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
1516 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(ceilf(a))));
1517 CHECK(isIdentical(effect, static_cast<double>(ceilf(a))));
1518}
1519
1520void testFloorArg(double a)
1521{
1522 Procedure proc;
1523 BasicBlock* root = proc.addBlock();
1524 root->appendNewControlValue(
1525 proc, Return, Origin(),
1526 root->appendNew<Value>(
1527 proc, Floor, Origin(),
1528 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
1529
1530 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a)));
1531}
1532
1533void testFloorImm(double a)
1534{
1535 Procedure proc;
1536 BasicBlock* root = proc.addBlock();
1537 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1538 root->appendNewControlValue(
1539 proc, Return, Origin(),
1540 root->appendNew<Value>(proc, Floor, Origin(), argument));
1541
1542 CHECK(isIdentical(compileAndRun<double>(proc), floor(a)));
1543}
1544
1545void testFloorMem(double a)
1546{
1547 Procedure proc;
1548 BasicBlock* root = proc.addBlock();
1549 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1550 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
1551 root->appendNewControlValue(
1552 proc, Return, Origin(),
1553 root->appendNew<Value>(proc, Floor, Origin(), loadDouble));
1554
1555 CHECK(isIdentical(compileAndRun<double>(proc, &a), floor(a)));
1556}
1557
1558void testFloorFloorArg(double a)
1559{
1560 Procedure proc;
1561 BasicBlock* root = proc.addBlock();
1562 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(),
1563 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1564 Value* secondFloor = root->appendNew<Value>(proc, Floor, Origin(), firstFloor);
1565 root->appendNewControlValue(proc, Return, Origin(), secondFloor);
1566
1567 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a)));
1568}
1569
1570void testCeilFloorArg(double a)
1571{
1572 Procedure proc;
1573 BasicBlock* root = proc.addBlock();
1574 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(),
1575 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1576 Value* wrappingCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstFloor);
1577 root->appendNewControlValue(proc, Return, Origin(), wrappingCeil);
1578
1579 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a)));
1580}
1581
1582void testFloorIToD64(int64_t a)
1583{
1584 Procedure proc;
1585 BasicBlock* root = proc.addBlock();
1586 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1587 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
1588
1589 root->appendNewControlValue(
1590 proc, Return, Origin(),
1591 root->appendNew<Value>(proc, Floor, Origin(), argumentAsDouble));
1592
1593 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(static_cast<double>(a))));
1594}
1595
1596void testFloorIToD32(int64_t a)
1597{
1598 Procedure proc;
1599 BasicBlock* root = proc.addBlock();
1600 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
1601 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1602 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
1603
1604 root->appendNewControlValue(
1605 proc, Return, Origin(),
1606 root->appendNew<Value>(proc, Floor, Origin(), argumentAsDouble));
1607
1608 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(static_cast<double>(a))));
1609}
1610
1611void testFloorArg(float a)
1612{
1613 Procedure proc;
1614 BasicBlock* root = proc.addBlock();
1615 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1616 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1617 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1618 Value* result = root->appendNew<Value>(proc, Floor, Origin(), argument);
1619 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1620 root->appendNewControlValue(proc, Return, Origin(), result32);
1621
1622 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a))));
1623}
1624
1625void testFloorImm(float a)
1626{
1627 Procedure proc;
1628 BasicBlock* root = proc.addBlock();
1629 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1630 Value* result = root->appendNew<Value>(proc, Floor, Origin(), argument);
1631 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1632 root->appendNewControlValue(proc, Return, Origin(), result32);
1633
1634 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a))));
1635}
1636
1637void testFloorMem(float a)
1638{
1639 Procedure proc;
1640 BasicBlock* root = proc.addBlock();
1641 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1642 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
1643 Value* result = root->appendNew<Value>(proc, Floor, Origin(), loadFloat);
1644 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1645 root->appendNewControlValue(proc, Return, Origin(), result32);
1646
1647 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(floorf(a))));
1648}
1649
1650void testFloorFloorArg(float a)
1651{
1652 Procedure proc;
1653 BasicBlock* root = proc.addBlock();
1654 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1655 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1656 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1657 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), argument);
1658 Value* secondFloor = root->appendNew<Value>(proc, Floor, Origin(), firstFloor);
1659 root->appendNewControlValue(proc, Return, Origin(), secondFloor);
1660
1661 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), floorf(a)));
1662}
1663
1664void testCeilFloorArg(float a)
1665{
1666 Procedure proc;
1667 BasicBlock* root = proc.addBlock();
1668 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1669 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1670 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1671 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), argument);
1672 Value* wrappingCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstFloor);
1673 root->appendNewControlValue(proc, Return, Origin(), wrappingCeil);
1674
1675 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), floorf(a)));
1676}
1677
1678void testFloorArgWithUselessDoubleConversion(float a)
1679{
1680 Procedure proc;
1681 BasicBlock* root = proc.addBlock();
1682 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1683 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1684 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1685 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1686 Value* result = root->appendNew<Value>(proc, Floor, Origin(), asDouble);
1687 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1688 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1689 root->appendNewControlValue(proc, Return, Origin(), result32);
1690
1691 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a))));
1692}
1693
1694void testFloorArgWithEffectfulDoubleConversion(float a)
1695{
1696 Procedure proc;
1697 BasicBlock* root = proc.addBlock();
1698 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1699 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1700 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1701 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1702 Value* result = root->appendNew<Value>(proc, Floor, Origin(), asDouble);
1703 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1704 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1705 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1706 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
1707 root->appendNewControlValue(proc, Return, Origin(), result32);
1708
1709 double effect = 0;
1710 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
1711 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(floorf(a))));
1712 CHECK(isIdentical(effect, static_cast<double>(floorf(a))));
1713}
1714
1715double correctSqrt(double value)
1716{
1717#if CPU(X86) || CPU(X86_64)
1718 double result;
1719 asm ("sqrtsd %1, %0" : "=x"(result) : "x"(value));
1720 return result;
1721#else
1722 return sqrt(value);
1723#endif
1724}
1725
1726void testSqrtArg(double a)
1727{
1728 Procedure proc;
1729 BasicBlock* root = proc.addBlock();
1730 root->appendNewControlValue(
1731 proc, Return, Origin(),
1732 root->appendNew<Value>(
1733 proc, Sqrt, Origin(),
1734 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
1735
1736 CHECK(isIdentical(compileAndRun<double>(proc, a), correctSqrt(a)));
1737}
1738
1739void testSqrtImm(double a)
1740{
1741 Procedure proc;
1742 BasicBlock* root = proc.addBlock();
1743 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1744 root->appendNewControlValue(
1745 proc, Return, Origin(),
1746 root->appendNew<Value>(proc, Sqrt, Origin(), argument));
1747
1748 CHECK(isIdentical(compileAndRun<double>(proc), correctSqrt(a)));
1749}
1750
1751void testSqrtMem(double a)
1752{
1753 Procedure proc;
1754 BasicBlock* root = proc.addBlock();
1755 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1756 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
1757 root->appendNewControlValue(
1758 proc, Return, Origin(),
1759 root->appendNew<Value>(proc, Sqrt, Origin(), loadDouble));
1760
1761 CHECK(isIdentical(compileAndRun<double>(proc, &a), correctSqrt(a)));
1762}
1763
1764void testSqrtArg(float a)
1765{
1766 Procedure proc;
1767 BasicBlock* root = proc.addBlock();
1768 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1769 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1770 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1771 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument);
1772 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1773 root->appendNewControlValue(proc, Return, Origin(), result32);
1774
1775 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
1776}
1777
1778void testSqrtImm(float a)
1779{
1780 Procedure proc;
1781 BasicBlock* root = proc.addBlock();
1782 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1783 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument);
1784 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1785 root->appendNewControlValue(proc, Return, Origin(), result32);
1786
1787 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
1788}
1789
1790void testSqrtMem(float a)
1791{
1792 Procedure proc;
1793 BasicBlock* root = proc.addBlock();
1794 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1795 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
1796 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), loadFloat);
1797 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1798 root->appendNewControlValue(proc, Return, Origin(), result32);
1799
1800 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
1801}
1802
1803void testSqrtArgWithUselessDoubleConversion(float a)
1804{
1805 Procedure proc;
1806 BasicBlock* root = proc.addBlock();
1807 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1808 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1809 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1810 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1811 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble);
1812 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1813 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1814 root->appendNewControlValue(proc, Return, Origin(), result32);
1815
1816 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
1817}
1818
1819void testSqrtArgWithEffectfulDoubleConversion(float a)
1820{
1821 Procedure proc;
1822 BasicBlock* root = proc.addBlock();
1823 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1824 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1825 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1826 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1827 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble);
1828 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1829 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1830 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1831 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
1832 root->appendNewControlValue(proc, Return, Origin(), result32);
1833
1834 double effect = 0;
1835 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
1836 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
1837 double expected = static_cast<double>(correctSqrt(a));
1838 CHECK(isIdentical(effect, expected));
1839}
1840
1841void testCompareTwoFloatToDouble(float a, float b)
1842{
1843 Procedure proc;
1844 BasicBlock* root = proc.addBlock();
1845
1846 Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(),
1847 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1848 Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32);
1849 Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float);
1850
1851 Value* arg2As32 = root->appendNew<Value>(proc, Trunc, Origin(),
1852 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1853 Value* arg2Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg2As32);
1854 Value* arg2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg2Float);
1855 Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble);
1856
1857 root->appendNewControlValue(proc, Return, Origin(), equal);
1858
1859 CHECK(compileAndRun<int64_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)) == (a == b));
1860}
1861
1862void testCompareOneFloatToDouble(float a, double b)
1863{
1864 Procedure proc;
1865 BasicBlock* root = proc.addBlock();
1866
1867 Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(),
1868 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1869 Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32);
1870 Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float);
1871
1872 Value* arg2AsDouble = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1873 Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble);
1874
1875 root->appendNewControlValue(proc, Return, Origin(), equal);
1876
1877 CHECK(compileAndRun<int64_t>(proc, bitwise_cast<int32_t>(a), b) == (a == b));
1878}
1879
1880void testCompareFloatToDoubleThroughPhi(float a, float b)
1881{
1882 Procedure proc;
1883 BasicBlock* root = proc.addBlock();
1884 BasicBlock* thenCase = proc.addBlock();
1885 BasicBlock* elseCase = proc.addBlock();
1886 BasicBlock* tail = proc.addBlock();
1887
1888 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1889
1890 Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(),
1891 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1892 Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32);
1893 Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float);
1894
1895 Value* arg2AsDouble = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1896 Value* arg2AsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), arg2AsDouble);
1897 Value* arg2AsFRoundedDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg2AsFloat);
1898
1899 root->appendNewControlValue(
1900 proc, Branch, Origin(),
1901 condition,
1902 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1903
1904 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), arg1AsDouble);
1905 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
1906
1907 Value* elseConst = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1908 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), elseConst);
1909 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
1910
1911 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
1912 thenValue->setPhi(doubleInput);
1913 elseValue->setPhi(doubleInput);
1914 Value* equal = tail->appendNew<Value>(proc, Equal, Origin(), doubleInput, arg2AsFRoundedDouble);
1915 tail->appendNewControlValue(proc, Return, Origin(), equal);
1916
1917 auto code = compileProc(proc);
1918 int32_t integerA = bitwise_cast<int32_t>(a);
1919 double doubleB = b;
1920 CHECK(invoke<int64_t>(*code, 1, integerA, doubleB) == (a == b));
1921 CHECK(invoke<int64_t>(*code, 0, integerA, doubleB) == (b == 0));
1922}
1923
1924void testDoubleToFloatThroughPhi(float value)
1925{
1926 // Simple case of:
1927 // if (a) {
1928 // x = DoubleAdd(a, b)
1929 // else
1930 // x = DoubleAdd(a, c)
1931 // DoubleToFloat(x)
1932 //
1933 // Both Adds can be converted to float add.
1934 Procedure proc;
1935 BasicBlock* root = proc.addBlock();
1936 BasicBlock* thenCase = proc.addBlock();
1937 BasicBlock* elseCase = proc.addBlock();
1938 BasicBlock* tail = proc.addBlock();
1939
1940 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1941 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1942 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1943 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1944 Value* argAsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1945
1946 root->appendNewControlValue(
1947 proc, Branch, Origin(),
1948 condition,
1949 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1950
1951 Value* postitiveConst = thenCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5f);
1952 Value* thenAdd = thenCase->appendNew<Value>(proc, Add, Origin(), argAsDouble, postitiveConst);
1953 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), thenAdd);
1954 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
1955
1956 Value* elseConst = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), M_PI);
1957 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), elseConst);
1958 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
1959
1960 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
1961 thenValue->setPhi(doubleInput);
1962 elseValue->setPhi(doubleInput);
1963 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleInput);
1964 tail->appendNewControlValue(proc, Return, Origin(), floatResult);
1965
1966 auto code = compileProc(proc);
1967 CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + 42.5f));
1968 CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<float>(M_PI)));
1969}
1970
1971void testReduceFloatToDoubleValidates()
1972{
1973 // Simple case of:
1974 // f = DoubleToFloat(Bitcast(argGPR0))
1975 // if (a) {
1976 // x = FloatConst()
1977 // else
1978 // x = FloatConst()
1979 // p = Phi(x)
1980 // a = Mul(p, p)
1981 // b = Add(a, f)
1982 // c = Add(p, b)
1983 // Return(c)
1984 //
1985 // This should not crash in the validator after ReduceFloatToDouble.
1986 Procedure proc;
1987 BasicBlock* root = proc.addBlock();
1988 BasicBlock* thenCase = proc.addBlock();
1989 BasicBlock* elseCase = proc.addBlock();
1990 BasicBlock* tail = proc.addBlock();
1991
1992 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1993 Value* thingy = root->appendNew<Value>(proc, BitwiseCast, Origin(), condition);
1994 thingy = root->appendNew<Value>(proc, DoubleToFloat, Origin(), thingy); // Make the phase think it has work to do.
1995 root->appendNewControlValue(
1996 proc, Branch, Origin(),
1997 condition,
1998 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1999
2000 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(),
2001 thenCase->appendNew<ConstFloatValue>(proc, Origin(), 11.5));
2002 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2003
2004 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(),
2005 elseCase->appendNew<ConstFloatValue>(proc, Origin(), 10.5));
2006 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2007
2008 Value* phi = tail->appendNew<Value>(proc, Phi, Float, Origin());
2009 thenValue->setPhi(phi);
2010 elseValue->setPhi(phi);
2011 Value* result = tail->appendNew<Value>(proc, Mul, Origin(),
2012 phi, phi);
2013 result = tail->appendNew<Value>(proc, Add, Origin(),
2014 result,
2015 thingy);
2016 result = tail->appendNew<Value>(proc, Add, Origin(),
2017 phi,
2018 result);
2019 tail->appendNewControlValue(proc, Return, Origin(), result);
2020
2021 auto code = compileProc(proc);
2022 CHECK(isIdentical(invoke<float>(*code, 1), 11.5f * 11.5f + static_cast<float>(bitwise_cast<double>(static_cast<uint64_t>(1))) + 11.5f));
2023 CHECK(isIdentical(invoke<float>(*code, 0), 10.5f * 10.5f + static_cast<float>(bitwise_cast<double>(static_cast<uint64_t>(0))) + 10.5f));
2024}
2025
2026void testDoubleProducerPhiToFloatConversion(float value)
2027{
2028 Procedure proc;
2029 BasicBlock* root = proc.addBlock();
2030 BasicBlock* thenCase = proc.addBlock();
2031 BasicBlock* elseCase = proc.addBlock();
2032 BasicBlock* tail = proc.addBlock();
2033
2034 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2035 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2036 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2037 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2038
2039 root->appendNewControlValue(
2040 proc, Branch, Origin(),
2041 condition,
2042 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2043
2044 Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2045 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble);
2046 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2047
2048 Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
2049 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble);
2050 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2051
2052 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
2053 thenValue->setPhi(doubleInput);
2054 elseValue->setPhi(doubleInput);
2055
2056 Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2057 Value* finalAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain);
2058 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), finalAdd);
2059 tail->appendNewControlValue(proc, Return, Origin(), floatResult);
2060
2061 auto code = compileProc(proc);
2062 CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + value));
2063 CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), 42.5f + value));
2064}
2065
2066void testDoubleProducerPhiToFloatConversionWithDoubleConsumer(float value)
2067{
2068 // In this case, the Upsilon-Phi effectively contains a Float value, but it is used
2069 // as a Float and as a Double.
2070 Procedure proc;
2071 BasicBlock* root = proc.addBlock();
2072 BasicBlock* thenCase = proc.addBlock();
2073 BasicBlock* elseCase = proc.addBlock();
2074 BasicBlock* tail = proc.addBlock();
2075
2076 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2077 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2078 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2079 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2080
2081 root->appendNewControlValue(
2082 proc, Branch, Origin(),
2083 condition,
2084 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2085
2086 Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2087 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble);
2088 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2089
2090 Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
2091 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble);
2092 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2093
2094 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
2095 thenValue->setPhi(doubleInput);
2096 elseValue->setPhi(doubleInput);
2097
2098 Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2099 Value* floatAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain);
2100
2101 // FRound.
2102 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), floatAdd);
2103 Value* doubleResult = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatResult);
2104
2105 // This one *cannot* be eliminated
2106 Value* doubleAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, doubleResult);
2107
2108 tail->appendNewControlValue(proc, Return, Origin(), doubleAdd);
2109
2110 auto code = compileProc(proc);
2111 CHECK(isIdentical(invoke<double>(*code, 1, bitwise_cast<int32_t>(value)), (value + value) + static_cast<double>(value)));
2112 CHECK(isIdentical(invoke<double>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<double>((42.5f + value) + 42.5f)));
2113}
2114
2115void testDoubleProducerPhiWithNonFloatConst(float value, double constValue)
2116{
2117 Procedure proc;
2118 BasicBlock* root = proc.addBlock();
2119 BasicBlock* thenCase = proc.addBlock();
2120 BasicBlock* elseCase = proc.addBlock();
2121 BasicBlock* tail = proc.addBlock();
2122
2123 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2124 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2125 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2126 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2127
2128 root->appendNewControlValue(
2129 proc, Branch, Origin(),
2130 condition,
2131 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2132
2133 Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2134 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble);
2135 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2136
2137 Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), constValue);
2138 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble);
2139 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
2140
2141 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
2142 thenValue->setPhi(doubleInput);
2143 elseValue->setPhi(doubleInput);
2144
2145 Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2146 Value* finalAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain);
2147 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), finalAdd);
2148 tail->appendNewControlValue(proc, Return, Origin(), floatResult);
2149
2150 auto code = compileProc(proc);
2151 CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + value));
2152 CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<float>(constValue + value)));
2153}
2154
2155void testDoubleArgToInt64BitwiseCast(double value)
2156{
2157 Procedure proc;
2158 BasicBlock* root = proc.addBlock();
2159 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2160
2161 root->appendNewControlValue(
2162 proc, Return, Origin(),
2163 root->appendNew<Value>(
2164 proc, BitwiseCast, Origin(), argument));
2165
2166 CHECK(isIdentical(compileAndRun<int64_t>(proc, value), bitwise_cast<int64_t>(value)));
2167}
2168
2169void testDoubleImmToInt64BitwiseCast(double value)
2170{
2171 Procedure proc;
2172 BasicBlock* root = proc.addBlock();
2173 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value);
2174
2175 root->appendNewControlValue(
2176 proc, Return, Origin(),
2177 root->appendNew<Value>(
2178 proc, BitwiseCast, Origin(), argument));
2179
2180 CHECK(isIdentical(compileAndRun<int64_t>(proc), bitwise_cast<int64_t>(value)));
2181}
2182
2183void testTwoBitwiseCastOnDouble(double value)
2184{
2185 Procedure proc;
2186 BasicBlock* root = proc.addBlock();
2187 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2188 Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
2189 Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
2190 root->appendNewControlValue(proc, Return, Origin(), second);
2191
2192 CHECK(isIdentical(compileAndRun<double>(proc, value), value));
2193}
2194
2195void testBitwiseCastOnDoubleInMemory(double value)
2196{
2197 Procedure proc;
2198 BasicBlock* root = proc.addBlock();
2199 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2200 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
2201 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
2202 root->appendNewControlValue(proc, Return, Origin(), cast);
2203
2204 CHECK(isIdentical(compileAndRun<int64_t>(proc, &value), bitwise_cast<int64_t>(value)));
2205}
2206
2207void testBitwiseCastOnDoubleInMemoryIndexed(double value)
2208{
2209 Procedure proc;
2210 BasicBlock* root = proc.addBlock();
2211 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2212 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2213 Value* scaledOffset = root->appendNew<Value>(proc, Shl, Origin(),
2214 offset,
2215 root->appendNew<Const32Value>(proc, Origin(), 3));
2216 Value* address = root->appendNew<Value>(proc, Add, Origin(), base, scaledOffset);
2217 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
2218 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
2219 root->appendNewControlValue(proc, Return, Origin(), cast);
2220
2221 CHECK(isIdentical(compileAndRun<int64_t>(proc, &value, 0), bitwise_cast<int64_t>(value)));
2222}
2223
2224void testInt64BArgToDoubleBitwiseCast(int64_t value)
2225{
2226 Procedure proc;
2227 BasicBlock* root = proc.addBlock();
2228 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2229
2230 root->appendNewControlValue(
2231 proc, Return, Origin(),
2232 root->appendNew<Value>(
2233 proc, BitwiseCast, Origin(), argument));
2234
2235 CHECK(isIdentical(compileAndRun<double>(proc, value), bitwise_cast<double>(value)));
2236}
2237
2238void testInt64BImmToDoubleBitwiseCast(int64_t value)
2239{
2240 Procedure proc;
2241 BasicBlock* root = proc.addBlock();
2242 Value* argument = root->appendNew<Const64Value>(proc, Origin(), value);
2243
2244 root->appendNewControlValue(
2245 proc, Return, Origin(),
2246 root->appendNew<Value>(
2247 proc, BitwiseCast, Origin(), argument));
2248
2249 CHECK(isIdentical(compileAndRun<double>(proc), bitwise_cast<double>(value)));
2250}
2251
2252void testTwoBitwiseCastOnInt64(int64_t value)
2253{
2254 Procedure proc;
2255 BasicBlock* root = proc.addBlock();
2256 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2257 Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
2258 Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
2259 root->appendNewControlValue(proc, Return, Origin(), second);
2260
2261 CHECK(isIdentical(compileAndRun<int64_t>(proc, value), value));
2262}
2263
2264void testBitwiseCastOnInt64InMemory(int64_t value)
2265{
2266 Procedure proc;
2267 BasicBlock* root = proc.addBlock();
2268 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2269 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2270 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
2271 root->appendNewControlValue(proc, Return, Origin(), cast);
2272
2273 CHECK(isIdentical(compileAndRun<double>(proc, &value), bitwise_cast<double>(value)));
2274}
2275
2276void testBitwiseCastOnInt64InMemoryIndexed(int64_t value)
2277{
2278 Procedure proc;
2279 BasicBlock* root = proc.addBlock();
2280 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2281 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2282 Value* scaledOffset = root->appendNew<Value>(proc, Shl, Origin(),
2283 offset,
2284 root->appendNew<Const32Value>(proc, Origin(), 3));
2285 Value* address = root->appendNew<Value>(proc, Add, Origin(), base, scaledOffset);
2286 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2287 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
2288 root->appendNewControlValue(proc, Return, Origin(), cast);
2289
2290 CHECK(isIdentical(compileAndRun<double>(proc, &value, 0), bitwise_cast<double>(value)));
2291}
2292
2293void testFloatImmToInt32BitwiseCast(float value)
2294{
2295 Procedure proc;
2296 BasicBlock* root = proc.addBlock();
2297 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value);
2298
2299 root->appendNewControlValue(
2300 proc, Return, Origin(),
2301 root->appendNew<Value>(
2302 proc, BitwiseCast, Origin(), argument));
2303
2304 CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(value)));
2305}
2306
2307void testBitwiseCastOnFloatInMemory(float value)
2308{
2309 Procedure proc;
2310 BasicBlock* root = proc.addBlock();
2311 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2312 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
2313 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat);
2314 root->appendNewControlValue(proc, Return, Origin(), cast);
2315
2316 CHECK(isIdentical(compileAndRun<int32_t>(proc, &value), bitwise_cast<int32_t>(value)));
2317}
2318
2319void testInt32BArgToFloatBitwiseCast(int32_t value)
2320{
2321 Procedure proc;
2322 BasicBlock* root = proc.addBlock();
2323 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2324
2325 root->appendNewControlValue(
2326 proc, Return, Origin(),
2327 root->appendNew<Value>(
2328 proc, BitwiseCast, Origin(), argument));
2329
2330 CHECK(isIdentical(compileAndRun<float>(proc, value), bitwise_cast<float>(value)));
2331}
2332
2333void testInt32BImmToFloatBitwiseCast(int32_t value)
2334{
2335 Procedure proc;
2336 BasicBlock* root = proc.addBlock();
2337 Value* argument = root->appendNew<Const64Value>(proc, Origin(), value);
2338
2339 root->appendNewControlValue(
2340 proc, Return, Origin(),
2341 root->appendNew<Value>(
2342 proc, BitwiseCast, Origin(), argument));
2343
2344 CHECK(isIdentical(compileAndRun<float>(proc), bitwise_cast<float>(value)));
2345}
2346
2347void testTwoBitwiseCastOnInt32(int32_t value)
2348{
2349 Procedure proc;
2350 BasicBlock* root = proc.addBlock();
2351 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2352 Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
2353 Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
2354 root->appendNewControlValue(proc, Return, Origin(), second);
2355
2356 CHECK(isIdentical(compileAndRun<int32_t>(proc, value), value));
2357}
2358
2359void testBitwiseCastOnInt32InMemory(int32_t value)
2360{
2361 Procedure proc;
2362 BasicBlock* root = proc.addBlock();
2363 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2364 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2365 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat);
2366 root->appendNewControlValue(proc, Return, Origin(), cast);
2367
2368 CHECK(isIdentical(compileAndRun<float>(proc, &value), bitwise_cast<float>(value)));
2369}
2370
2371void testConvertDoubleToFloatArg(double value)
2372{
2373 Procedure proc;
2374 BasicBlock* root = proc.addBlock();
2375 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2376 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
2377 root->appendNewControlValue(proc, Return, Origin(), asFloat);
2378
2379 CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value)));
2380}
2381
2382void testConvertDoubleToFloatImm(double value)
2383{
2384 Procedure proc;
2385 BasicBlock* root = proc.addBlock();
2386 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value);
2387 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
2388 root->appendNewControlValue(proc, Return, Origin(), asFloat);
2389
2390 CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
2391}
2392
2393void testConvertDoubleToFloatMem(double value)
2394{
2395 Procedure proc;
2396 BasicBlock* root = proc.addBlock();
2397 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2398 MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
2399 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble);
2400 root->appendNewControlValue(proc, Return, Origin(), asFloat);
2401
2402 CHECK(isIdentical(compileAndRun<float>(proc, &value), static_cast<float>(value)));
2403}
2404
2405void testConvertFloatToDoubleArg(float value)
2406{
2407 Procedure proc;
2408 BasicBlock* root = proc.addBlock();
2409 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2410 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2411 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2412 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2413 root->appendNewControlValue(proc, Return, Origin(), asDouble);
2414
2415 CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int32_t>(value)), static_cast<double>(value)));
2416}
2417
2418void testConvertFloatToDoubleImm(float value)
2419{
2420 Procedure proc;
2421 BasicBlock* root = proc.addBlock();
2422 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value);
2423 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument);
2424 root->appendNewControlValue(proc, Return, Origin(), asDouble);
2425
2426 CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
2427}
2428
2429void testConvertFloatToDoubleMem(float value)
2430{
2431 Procedure proc;
2432 BasicBlock* root = proc.addBlock();
2433 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2434 MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
2435 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat);
2436 root->appendNewControlValue(proc, Return, Origin(), asDouble);
2437
2438 CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(value)));
2439}
2440
2441void testConvertDoubleToFloatToDoubleToFloat(double value)
2442{
2443 Procedure proc;
2444 BasicBlock* root = proc.addBlock();
2445 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2446 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
2447 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
2448 Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble);
2449 root->appendNewControlValue(proc, Return, Origin(), asFloatAgain);
2450
2451 CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value)));
2452}
2453
2454void testLoadFloatConvertDoubleConvertFloatStoreFloat(float value)
2455{
2456 Procedure proc;
2457 BasicBlock* root = proc.addBlock();
2458 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2459 Value* dst = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2460 MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), src);
2461 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat);
2462 Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble);
2463 root->appendNew<MemoryValue>(proc, Store, Origin(), asFloatAgain, dst);
2464
2465 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2466
2467 float input = value;
2468 float output = 0.;
2469 CHECK(!compileAndRun<int64_t>(proc, &input, &output));
2470 CHECK(isIdentical(input, output));
2471}
2472
2473void testFroundArg(double value)
2474{
2475 Procedure proc;
2476 BasicBlock* root = proc.addBlock();
2477 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2478 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
2479 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
2480 root->appendNewControlValue(proc, Return, Origin(), asDouble);
2481
2482 CHECK(isIdentical(compileAndRun<double>(proc, value), static_cast<double>(static_cast<float>(value))));
2483}
2484
2485void testFroundMem(double value)
2486{
2487 Procedure proc;
2488 BasicBlock* root = proc.addBlock();
2489 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2490 MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
2491 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble);
2492 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
2493 root->appendNewControlValue(proc, Return, Origin(), asDouble);
2494
2495 CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(static_cast<float>(value))));
2496}
2497
2498void testIToD64Arg()
2499{
2500 Procedure proc;
2501 BasicBlock* root = proc.addBlock();
2502 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2503 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
2504 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
2505
2506 auto code = compileProc(proc);
2507 for (auto testValue : int64Operands())
2508 CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value)));
2509}
2510
2511void testIToF64Arg()
2512{
2513 Procedure proc;
2514 BasicBlock* root = proc.addBlock();
2515 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2516 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src);
2517 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
2518
2519 auto code = compileProc(proc);
2520 for (auto testValue : int64Operands())
2521 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
2522}
2523
2524void testIToD32Arg()
2525{
2526 Procedure proc;
2527 BasicBlock* root = proc.addBlock();
2528 Value* src = root->appendNew<Value>(proc, Trunc, Origin(),
2529 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2530 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
2531 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
2532
2533 auto code = compileProc(proc);
2534 for (auto testValue : int32Operands())
2535 CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value)));
2536}
2537
2538void testIToF32Arg()
2539{
2540 Procedure proc;
2541 BasicBlock* root = proc.addBlock();
2542 Value* src = root->appendNew<Value>(proc, Trunc, Origin(),
2543 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2544 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src);
2545 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
2546
2547 auto code = compileProc(proc);
2548 for (auto testValue : int32Operands())
2549 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
2550}
2551
2552void testIToD64Mem()
2553{
2554 Procedure proc;
2555 BasicBlock* root = proc.addBlock();
2556 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2557 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2558 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc);
2559 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
2560
2561 auto code = compileProc(proc);
2562 int64_t inMemoryValue;
2563 for (auto testValue : int64Operands()) {
2564 inMemoryValue = testValue.value;
2565 CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value)));
2566 CHECK(inMemoryValue == testValue.value);
2567 }
2568}
2569
2570void testIToF64Mem()
2571{
2572 Procedure proc;
2573 BasicBlock* root = proc.addBlock();
2574 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2575 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2576 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc);
2577 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
2578
2579 auto code = compileProc(proc);
2580 int64_t inMemoryValue;
2581 for (auto testValue : int64Operands()) {
2582 inMemoryValue = testValue.value;
2583 CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value)));
2584 CHECK(inMemoryValue == testValue.value);
2585 }
2586}
2587
2588void testIToD32Mem()
2589{
2590 Procedure proc;
2591 BasicBlock* root = proc.addBlock();
2592 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2593 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2594 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc);
2595 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
2596
2597 auto code = compileProc(proc);
2598 int32_t inMemoryValue;
2599 for (auto testValue : int32Operands()) {
2600 inMemoryValue = testValue.value;
2601 CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value)));
2602 CHECK(inMemoryValue == testValue.value);
2603 }
2604}
2605
2606void testIToF32Mem()
2607{
2608 Procedure proc;
2609 BasicBlock* root = proc.addBlock();
2610 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2611 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2612 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc);
2613 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
2614
2615 auto code = compileProc(proc);
2616 int32_t inMemoryValue;
2617 for (auto testValue : int32Operands()) {
2618 inMemoryValue = testValue.value;
2619 CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value)));
2620 CHECK(inMemoryValue == testValue.value);
2621 }
2622}
2623
2624void testIToD64Imm(int64_t value)
2625{
2626 Procedure proc;
2627 BasicBlock* root = proc.addBlock();
2628 Value* src = root->appendNew<Const64Value>(proc, Origin(), value);
2629 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src);
2630 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
2631 CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
2632}
2633
2634void testIToF64Imm(int64_t value)
2635{
2636 Procedure proc;
2637 BasicBlock* root = proc.addBlock();
2638 Value* src = root->appendNew<Const64Value>(proc, Origin(), value);
2639 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src);
2640 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
2641 CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
2642}
2643
2644void testIToD32Imm(int32_t value)
2645{
2646 Procedure proc;
2647 BasicBlock* root = proc.addBlock();
2648 Value* src = root->appendNew<Const32Value>(proc, Origin(), value);
2649 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src);
2650 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
2651 CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
2652}
2653
2654void testIToF32Imm(int32_t value)
2655{
2656 Procedure proc;
2657 BasicBlock* root = proc.addBlock();
2658 Value* src = root->appendNew<Const32Value>(proc, Origin(), value);
2659 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src);
2660 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
2661 CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
2662}
2663
2664void testIToDReducedToIToF64Arg()
2665{
2666 Procedure proc;
2667 BasicBlock* root = proc.addBlock();
2668 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2669 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
2670 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble);
2671 root->appendNewControlValue(proc, Return, Origin(), floatResult);
2672
2673 auto code = compileProc(proc);
2674 for (auto testValue : int64Operands())
2675 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
2676}
2677
2678void testIToDReducedToIToF32Arg()
2679{
2680 Procedure proc;
2681 BasicBlock* root = proc.addBlock();
2682 Value* src = root->appendNew<Value>(proc, Trunc, Origin(),
2683 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2684 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
2685 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble);
2686 root->appendNewControlValue(proc, Return, Origin(), floatResult);
2687
2688 auto code = compileProc(proc);
2689 for (auto testValue : int32Operands())
2690 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
2691}
2692
2693void testStore32(int value)
2694{
2695 Procedure proc;
2696 BasicBlock* root = proc.addBlock();
2697 int slot = 0xbaadbeef;
2698 root->appendNew<MemoryValue>(
2699 proc, Store, Origin(),
2700 root->appendNew<Value>(
2701 proc, Trunc, Origin(),
2702 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2703 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0);
2704 root->appendNewControlValue(
2705 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2706
2707 CHECK(!compileAndRun<int>(proc, value));
2708 CHECK(slot == value);
2709}
2710
2711void testStoreConstant(int value)
2712{
2713 Procedure proc;
2714 BasicBlock* root = proc.addBlock();
2715 int slot = 0xbaadbeef;
2716 root->appendNew<MemoryValue>(
2717 proc, Store, Origin(),
2718 root->appendNew<Const32Value>(proc, Origin(), value),
2719 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0);
2720 root->appendNewControlValue(
2721 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2722
2723 CHECK(!compileAndRun<int>(proc));
2724 CHECK(slot == value);
2725}
2726
2727void testStoreConstantPtr(intptr_t value)
2728{
2729 Procedure proc;
2730 BasicBlock* root = proc.addBlock();
2731 intptr_t slot;
2732#if CPU(ADDRESS64)
2733 slot = (static_cast<intptr_t>(0xbaadbeef) << 32) + static_cast<intptr_t>(0xbaadbeef);
2734#else
2735 slot = 0xbaadbeef;
2736#endif
2737 root->appendNew<MemoryValue>(
2738 proc, Store, Origin(),
2739 root->appendNew<ConstPtrValue>(proc, Origin(), value),
2740 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0);
2741 root->appendNewControlValue(
2742 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2743
2744 CHECK(!compileAndRun<int>(proc));
2745 CHECK(slot == value);
2746}
2747
2748void testStore8Arg()
2749{
2750 { // Direct addressing.
2751 Procedure proc;
2752 BasicBlock* root = proc.addBlock();
2753
2754 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
2755 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2756 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2757
2758 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
2759 root->appendNewControlValue(proc, Return, Origin(), value);
2760
2761 int8_t storage = 0;
2762 CHECK(compileAndRun<int64_t>(proc, 42, &storage) == 42);
2763 CHECK(storage == 42);
2764 }
2765
2766 { // Indexed addressing.
2767 Procedure proc;
2768 BasicBlock* root = proc.addBlock();
2769
2770 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
2771 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2772 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2773 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2774 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
2775
2776 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
2777 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
2778
2779 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
2780 root->appendNewControlValue(proc, Return, Origin(), value);
2781
2782 int8_t storage = 0;
2783 CHECK(compileAndRun<int64_t>(proc, 42, &storage, 1) == 42);
2784 CHECK(storage == 42);
2785 }
2786}
2787
2788void testStore8Imm()
2789{
2790 { // Direct addressing.
2791 Procedure proc;
2792 BasicBlock* root = proc.addBlock();
2793
2794 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
2795 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2796
2797 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
2798 root->appendNewControlValue(proc, Return, Origin(), value);
2799
2800 int8_t storage = 0;
2801 CHECK(compileAndRun<int64_t>(proc, &storage) == 42);
2802 CHECK(storage == 42);
2803 }
2804
2805 { // Indexed addressing.
2806 Procedure proc;
2807 BasicBlock* root = proc.addBlock();
2808
2809 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
2810 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2811 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2812 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
2813
2814 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
2815 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
2816
2817 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
2818 root->appendNewControlValue(proc, Return, Origin(), value);
2819
2820 int8_t storage = 0;
2821 CHECK(compileAndRun<int64_t>(proc, &storage, 1) == 42);
2822 CHECK(storage == 42);
2823 }
2824}
2825
2826void testStorePartial8BitRegisterOnX86()
2827{
2828 Procedure proc;
2829 BasicBlock* root = proc.addBlock();
2830
2831 // We want to have this in ECX.
2832 Value* returnValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2833
2834 // We want this suck in EDX.
2835 Value* whereToStore = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2836
2837 // The patch point is there to help us force the hand of the compiler.
2838 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2839
2840 // For the value above to be materialized and give the allocator
2841 // a stronger insentive to name those register the way we need.
2842 patchpoint->append(ConstrainedValue(returnValue, ValueRep(GPRInfo::regT3)));
2843 patchpoint->append(ConstrainedValue(whereToStore, ValueRep(GPRInfo::regT2)));
2844
2845 // We'll produce EDI.
2846 patchpoint->resultConstraints = { ValueRep::reg(GPRInfo::regT6) };
2847
2848 // Give the allocator a good reason not to use any other register.
2849 RegisterSet clobberSet = RegisterSet::allGPRs();
2850 clobberSet.exclude(RegisterSet::stackRegisters());
2851 clobberSet.exclude(RegisterSet::reservedHardwareRegisters());
2852 clobberSet.clear(GPRInfo::regT3);
2853 clobberSet.clear(GPRInfo::regT2);
2854 clobberSet.clear(GPRInfo::regT6);
2855 patchpoint->clobberLate(clobberSet);
2856
2857 // Set EDI.
2858 patchpoint->setGenerator(
2859 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2860 AllowMacroScratchRegisterUsage allowScratch(jit);
2861 jit.xor64(params[0].gpr(), params[0].gpr());
2862 });
2863
2864 // If everything went well, we should have the big number in eax,
2865 // patchpoint == EDI and whereToStore = EDX.
2866 // Since EDI == 5, and AH = 5 on 8 bit store, this would go wrong
2867 // if we use X86 partial registers.
2868 root->appendNew<MemoryValue>(proc, Store8, Origin(), patchpoint, whereToStore);
2869
2870 root->appendNewControlValue(proc, Return, Origin(), returnValue);
2871
2872 int8_t storage = 0xff;
2873 CHECK(compileAndRun<int64_t>(proc, 0x12345678abcdef12, &storage) == 0x12345678abcdef12);
2874 CHECK(!storage);
2875}
2876
2877void testStore16Arg()
2878{
2879 { // Direct addressing.
2880 Procedure proc;
2881 BasicBlock* root = proc.addBlock();
2882
2883 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
2884 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2885 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2886
2887 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
2888 root->appendNewControlValue(proc, Return, Origin(), value);
2889
2890 int16_t storage = -1;
2891 CHECK(compileAndRun<int64_t>(proc, 42, &storage) == 42);
2892 CHECK(storage == 42);
2893 }
2894
2895 { // Indexed addressing.
2896 Procedure proc;
2897 BasicBlock* root = proc.addBlock();
2898
2899 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
2900 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2901 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2902 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2903 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
2904
2905 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
2906 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
2907
2908 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
2909 root->appendNewControlValue(proc, Return, Origin(), value);
2910
2911 int16_t storage = -1;
2912 CHECK(compileAndRun<int64_t>(proc, 42, &storage, 1) == 42);
2913 CHECK(storage == 42);
2914 }
2915}
2916
2917void testStore16Imm()
2918{
2919 { // Direct addressing.
2920 Procedure proc;
2921 BasicBlock* root = proc.addBlock();
2922
2923 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
2924 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2925
2926 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
2927 root->appendNewControlValue(proc, Return, Origin(), value);
2928
2929 int16_t storage = -1;
2930 CHECK(compileAndRun<int64_t>(proc, &storage) == 42);
2931 CHECK(storage == 42);
2932 }
2933
2934 { // Indexed addressing.
2935 Procedure proc;
2936 BasicBlock* root = proc.addBlock();
2937
2938 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
2939 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2940 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2941 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
2942
2943 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
2944 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
2945
2946 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
2947 root->appendNewControlValue(proc, Return, Origin(), value);
2948
2949 int16_t storage = -1;
2950 CHECK(compileAndRun<int64_t>(proc, &storage, 1) == 42);
2951 CHECK(storage == 42);
2952 }
2953}
2954
2955void testTrunc(int64_t value)
2956{
2957 Procedure proc;
2958 BasicBlock* root = proc.addBlock();
2959 root->appendNewControlValue(
2960 proc, Return, Origin(),
2961 root->appendNew<Value>(
2962 proc, Trunc, Origin(),
2963 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2964
2965 CHECK(compileAndRun<int>(proc, value) == static_cast<int>(value));
2966}
2967
2968void testAdd1(int value)
2969{
2970 Procedure proc;
2971 BasicBlock* root = proc.addBlock();
2972 root->appendNewControlValue(
2973 proc, Return, Origin(),
2974 root->appendNew<Value>(
2975 proc, Add, Origin(),
2976 root->appendNew<Value>(
2977 proc, Trunc, Origin(),
2978 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2979 root->appendNew<Const32Value>(proc, Origin(), 1)));
2980
2981 CHECK(compileAndRun<int>(proc, value) == value + 1);
2982}
2983
2984void testAdd1Ptr(intptr_t value)
2985{
2986 Procedure proc;
2987 BasicBlock* root = proc.addBlock();
2988 root->appendNewControlValue(
2989 proc, Return, Origin(),
2990 root->appendNew<Value>(
2991 proc, Add, Origin(),
2992 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2993 root->appendNew<ConstPtrValue>(proc, Origin(), 1)));
2994
2995 CHECK(compileAndRun<intptr_t>(proc, value) == value + 1);
2996}
2997
2998void testNeg32(int32_t value)
2999{
3000 Procedure proc;
3001 BasicBlock* root = proc.addBlock();
3002 root->appendNewControlValue(
3003 proc, Return, Origin(),
3004 root->appendNew<Value>(
3005 proc, Sub, Origin(),
3006 root->appendNew<Const32Value>(proc, Origin(), 0),
3007 root->appendNew<Value>(
3008 proc, Trunc, Origin(),
3009 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3010
3011 CHECK(compileAndRun<int32_t>(proc, value) == -value);
3012}
3013
3014void testNegPtr(intptr_t value)
3015{
3016 Procedure proc;
3017 BasicBlock* root = proc.addBlock();
3018 root->appendNewControlValue(
3019 proc, Return, Origin(),
3020 root->appendNew<Value>(
3021 proc, Sub, Origin(),
3022 root->appendNew<ConstPtrValue>(proc, Origin(), 0),
3023 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3024
3025 CHECK(compileAndRun<intptr_t>(proc, value) == -value);
3026}
3027
3028void testStoreAddLoad32(int amount)
3029{
3030 Procedure proc;
3031 BasicBlock* root = proc.addBlock();
3032 int slot = 37;
3033 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
3034 root->appendNew<MemoryValue>(
3035 proc, Store, Origin(),
3036 root->appendNew<Value>(
3037 proc, Add, Origin(),
3038 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
3039 root->appendNew<Value>(
3040 proc, Trunc, Origin(),
3041 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
3042 slotPtr, 0);
3043 root->appendNewControlValue(
3044 proc, Return, Origin(),
3045 root->appendNew<Const32Value>(proc, Origin(), 0));
3046
3047 CHECK(!compileAndRun<int>(proc, amount));
3048 CHECK(slot == 37 + amount);
3049}
3050
3051// Make sure the compiler does not try to optimize anything out.
3052static NEVER_INLINE double zero()
3053{
3054 return 0.;
3055}
3056
3057static double negativeZero()
3058{
3059 return -zero();
3060}
3061
3062void addArgTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks)
3063{
3064 RUN(testAddArg(111));
3065 RUN(testAddArgs(1, 1));
3066 RUN(testAddArgs(1, 2));
3067 RUN(testAddArgImm(1, 2));
3068 RUN(testAddArgImm(0, 2));
3069 RUN(testAddArgImm(1, 0));
3070 RUN(testAddImmArg(1, 2));
3071 RUN(testAddImmArg(0, 2));
3072 RUN(testAddImmArg(1, 0));
3073 RUN_BINARY(testAddArgMem, int64Operands(), int64Operands());
3074 RUN_BINARY(testAddMemArg, int64Operands(), int64Operands());
3075 RUN_BINARY(testAddImmMem, int64Operands(), int64Operands());
3076 RUN_UNARY(testAddArg32, int32Operands());
3077 RUN(testAddArgs32(1, 1));
3078 RUN(testAddArgs32(1, 2));
3079 RUN_BINARY(testAddArgMem32, int32Operands(), int32Operands());
3080 RUN_BINARY(testAddMemArg32, int32Operands(), int32Operands());
3081 RUN_BINARY(testAddImmMem32, int32Operands(), int32Operands());
3082 RUN_BINARY(testAddNeg1, int32Operands(), int32Operands());
3083 RUN_BINARY(testAddNeg2, int32Operands(), int32Operands());
3084 RUN(testAddArgZeroImmZDef());
3085 RUN(testAddLoadTwice());
3086 RUN_TERNARY(testAddMulMulArgs, int64Operands(), int64Operands(), int64Operands());
3087
3088 RUN(testAddArgDouble(M_PI));
3089 RUN(testAddArgsDouble(M_PI, 1));
3090 RUN(testAddArgsDouble(M_PI, -M_PI));
3091 RUN(testAddArgImmDouble(M_PI, 1));
3092 RUN(testAddArgImmDouble(M_PI, 0));
3093 RUN(testAddArgImmDouble(M_PI, negativeZero()));
3094 RUN(testAddArgImmDouble(0, 0));
3095 RUN(testAddArgImmDouble(0, negativeZero()));
3096 RUN(testAddArgImmDouble(negativeZero(), 0));
3097 RUN(testAddArgImmDouble(negativeZero(), negativeZero()));
3098 RUN(testAddImmArgDouble(M_PI, 1));
3099 RUN(testAddImmArgDouble(M_PI, 0));
3100 RUN(testAddImmArgDouble(M_PI, negativeZero()));
3101 RUN(testAddImmArgDouble(0, 0));
3102 RUN(testAddImmArgDouble(0, negativeZero()));
3103 RUN(testAddImmArgDouble(negativeZero(), 0));
3104 RUN(testAddImmArgDouble(negativeZero(), negativeZero()));
3105 RUN(testAddImmsDouble(M_PI, 1));
3106 RUN(testAddImmsDouble(M_PI, 0));
3107 RUN(testAddImmsDouble(M_PI, negativeZero()));
3108 RUN(testAddImmsDouble(0, 0));
3109 RUN(testAddImmsDouble(0, negativeZero()));
3110 RUN(testAddImmsDouble(negativeZero(), negativeZero()));
3111 RUN_UNARY(testAddArgFloat, floatingPointOperands<float>());
3112 RUN_BINARY(testAddArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3113 RUN_BINARY(testAddFPRArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3114 RUN_BINARY(testAddArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3115 RUN_BINARY(testAddImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3116 RUN_BINARY(testAddImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3117 RUN_UNARY(testAddArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
3118 RUN_BINARY(testAddArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3119 RUN_BINARY(testAddArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3120
3121 RUN(testMulArg(5));
3122 RUN(testMulAddArg(5));
3123 RUN(testMulAddArg(85));
3124 RUN(testMulArgStore(5));
3125 RUN(testMulArgStore(85));
3126 RUN(testMulArgs(1, 1));
3127 RUN(testMulArgs(1, 2));
3128 RUN(testMulArgs(3, 3));
3129 RUN(testMulArgImm(1, 2));
3130 RUN(testMulArgImm(1, 4));
3131 RUN(testMulArgImm(1, 8));
3132 RUN(testMulArgImm(1, 16));
3133 RUN(testMulArgImm(1, 0x80000000llu));
3134 RUN(testMulArgImm(1, 0x800000000000llu));
3135 RUN(testMulArgImm(7, 2));
3136 RUN(testMulArgImm(7, 4));
3137 RUN(testMulArgImm(7, 8));
3138 RUN(testMulArgImm(7, 16));
3139 RUN(testMulArgImm(7, 0x80000000llu));
3140 RUN(testMulArgImm(7, 0x800000000000llu));
3141 RUN(testMulArgImm(-42, 2));
3142 RUN(testMulArgImm(-42, 4));
3143 RUN(testMulArgImm(-42, 8));
3144 RUN(testMulArgImm(-42, 16));
3145 RUN(testMulArgImm(-42, 0x80000000llu));
3146 RUN(testMulArgImm(-42, 0x800000000000llu));
3147 RUN(testMulArgImm(0, 2));
3148 RUN(testMulArgImm(1, 0));
3149 RUN(testMulArgImm(3, 3));
3150 RUN(testMulArgImm(3, -1));
3151 RUN(testMulArgImm(-3, -1));
3152 RUN(testMulArgImm(0, -1));
3153 RUN(testMulImmArg(1, 2));
3154 RUN(testMulImmArg(0, 2));
3155 RUN(testMulImmArg(1, 0));
3156 RUN(testMulImmArg(3, 3));
3157 RUN_BINARY(testMulImm32SignExtend, int32Operands(), int32Operands());
3158 RUN(testMulImm32SignExtend(0xFFFFFFFE, 0xFFFFFFFF));
3159 RUN(testMulImm32SignExtend(0xFFFFFFFF, 0xFFFFFFFE));
3160 RUN(testMulArgs32(1, 1));
3161 RUN(testMulArgs32(1, 2));
3162 RUN(testMulArgs32(0xFFFFFFFF, 0xFFFFFFFF));
3163 RUN(testMulArgs32(0xFFFFFFFE, 0xFFFFFFFF));
3164 RUN(testMulArgs32SignExtend(1, 1));
3165 RUN(testMulArgs32SignExtend(1, 2));
3166 RUN(testMulArgs32SignExtend(0xFFFFFFFF, 0xFFFFFFFF));
3167 RUN(testMulArgs32SignExtend(0xFFFFFFFE, 0xFFFFFFFF));
3168 RUN(testMulLoadTwice());
3169 RUN(testMulAddArgsLeft());
3170 RUN(testMulAddArgsRight());
3171 RUN(testMulAddArgsLeft32());
3172 RUN(testMulAddArgsRight32());
3173 RUN(testMulSubArgsLeft());
3174 RUN(testMulSubArgsRight());
3175 RUN(testMulSubArgsLeft32());
3176 RUN(testMulSubArgsRight32());
3177 RUN(testMulNegArgs());
3178 RUN(testMulNegArgs32());
3179
3180 RUN_BINARY(testMulArgNegArg, int64Operands(), int64Operands())
3181 RUN_BINARY(testMulNegArgArg, int64Operands(), int64Operands())
3182 RUN_UNARY(testMulArgDouble, floatingPointOperands<double>());
3183 RUN_BINARY(testMulArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3184 RUN_BINARY(testMulArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3185 RUN_BINARY(testMulImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3186 RUN_BINARY(testMulImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3187 RUN_UNARY(testMulArgFloat, floatingPointOperands<float>());
3188 RUN_BINARY(testMulArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3189 RUN_BINARY(testMulArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3190 RUN_BINARY(testMulImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3191 RUN_BINARY(testMulImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3192 RUN_UNARY(testMulArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
3193 RUN_BINARY(testMulArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3194 RUN_BINARY(testMulArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3195
3196 RUN(testDivArgDouble(M_PI));
3197 RUN(testDivArgsDouble(M_PI, 1));
3198 RUN(testDivArgsDouble(M_PI, -M_PI));
3199 RUN(testDivArgImmDouble(M_PI, 1));
3200 RUN(testDivArgImmDouble(M_PI, 0));
3201 RUN(testDivArgImmDouble(M_PI, negativeZero()));
3202 RUN(testDivArgImmDouble(0, 0));
3203 RUN(testDivArgImmDouble(0, negativeZero()));
3204 RUN(testDivArgImmDouble(negativeZero(), 0));
3205 RUN(testDivArgImmDouble(negativeZero(), negativeZero()));
3206 RUN(testDivImmArgDouble(M_PI, 1));
3207 RUN(testDivImmArgDouble(M_PI, 0));
3208 RUN(testDivImmArgDouble(M_PI, negativeZero()));
3209 RUN(testDivImmArgDouble(0, 0));
3210 RUN(testDivImmArgDouble(0, negativeZero()));
3211 RUN(testDivImmArgDouble(negativeZero(), 0));
3212 RUN(testDivImmArgDouble(negativeZero(), negativeZero()));
3213 RUN(testDivImmsDouble(M_PI, 1));
3214 RUN(testDivImmsDouble(M_PI, 0));
3215 RUN(testDivImmsDouble(M_PI, negativeZero()));
3216 RUN(testDivImmsDouble(0, 0));
3217 RUN(testDivImmsDouble(0, negativeZero()));
3218 RUN(testDivImmsDouble(negativeZero(), negativeZero()));
3219 RUN_UNARY(testDivArgFloat, floatingPointOperands<float>());
3220 RUN_BINARY(testDivArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3221 RUN_BINARY(testDivArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3222 RUN_BINARY(testDivImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3223 RUN_BINARY(testDivImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3224 RUN_UNARY(testDivArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
3225 RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3226 RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3227
3228 RUN_BINARY(testUDivArgsInt32, int32Operands(), int32Operands());
3229 RUN_BINARY(testUDivArgsInt64, int64Operands(), int64Operands());
3230
3231 RUN_UNARY(testModArgDouble, floatingPointOperands<double>());
3232 RUN_BINARY(testModArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3233 RUN_BINARY(testModArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3234 RUN_BINARY(testModImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3235 RUN_BINARY(testModImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3236 RUN_UNARY(testModArgFloat, floatingPointOperands<float>());
3237 RUN_BINARY(testModArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3238 RUN_BINARY(testModArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3239 RUN_BINARY(testModImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3240 RUN_BINARY(testModImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3241
3242 RUN_BINARY(testUModArgsInt32, int32Operands(), int32Operands());
3243 RUN_BINARY(testUModArgsInt64, int64Operands(), int64Operands());
3244
3245 RUN(testSubArg(24));
3246 RUN(testSubArgs(1, 1));
3247 RUN(testSubArgs(1, 2));
3248 RUN(testSubArgs(13, -42));
3249 RUN(testSubArgs(-13, 42));
3250 RUN(testSubArgImm(1, 1));
3251 RUN(testSubArgImm(1, 2));
3252 RUN(testSubArgImm(13, -42));
3253 RUN(testSubArgImm(-13, 42));
3254 RUN(testSubArgImm(42, 0));
3255 RUN(testSubImmArg(1, 1));
3256 RUN(testSubImmArg(1, 2));
3257 RUN(testSubImmArg(13, -42));
3258 RUN(testSubImmArg(-13, 42));
3259 RUN_BINARY(testSubArgMem, int64Operands(), int64Operands());
3260 RUN_BINARY(testSubMemArg, int64Operands(), int64Operands());
3261 RUN_BINARY(testSubImmMem, int32Operands(), int32Operands());
3262 RUN_BINARY(testSubMemImm, int32Operands(), int32Operands());
3263 RUN_BINARY(testSubNeg, int32Operands(), int32Operands());
3264 RUN_BINARY(testNegSub, int32Operands(), int32Operands());
3265 RUN_UNARY(testNegValueSubOne, int32Operands());
3266 RUN_BINARY(testNegMulArgImm, int64Operands(), int64Operands());
3267 RUN_TERNARY(testSubMulMulArgs, int64Operands(), int64Operands(), int64Operands());
3268
3269 RUN_TERNARY(testSubSub, int32Operands(), int32Operands(), int32Operands());
3270 RUN_TERNARY(testSubSub2, int32Operands(), int32Operands(), int32Operands());
3271 RUN_TERNARY(testSubAdd, int32Operands(), int32Operands(), int32Operands());
3272 RUN_BINARY(testSubFirstNeg, int32Operands(), int32Operands());
3273
3274 RUN(testSubArgs32(1, 1));
3275 RUN(testSubArgs32(1, 2));
3276 RUN(testSubArgs32(13, -42));
3277 RUN(testSubArgs32(-13, 42));
3278 RUN(testSubArgImm32(1, 1));
3279 RUN(testSubArgImm32(1, 2));
3280 RUN(testSubArgImm32(13, -42));
3281 RUN(testSubArgImm32(-13, 42));
3282 RUN(testSubImmArg32(1, 1));
3283 RUN(testSubImmArg32(1, 2));
3284 RUN(testSubImmArg32(13, -42));
3285 RUN(testSubImmArg32(-13, 42));
3286 RUN_BINARY(testSubArgMem32, int32Operands(), int32Operands());
3287 RUN_BINARY(testSubMemArg32, int32Operands(), int32Operands());
3288 RUN_BINARY(testSubImmMem32, int32Operands(), int32Operands());
3289 RUN_BINARY(testSubMemImm32, int32Operands(), int32Operands());
3290 RUN_UNARY(testNegValueSubOne32, int64Operands());
3291
3292 RUN_UNARY(testSubArgDouble, floatingPointOperands<double>());
3293 RUN_BINARY(testSubArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3294 RUN_BINARY(testSubArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3295 RUN_BINARY(testSubImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3296 RUN_BINARY(testSubImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3297 RUN_UNARY(testSubArgFloat, floatingPointOperands<float>());
3298 RUN_BINARY(testSubArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3299 RUN_BINARY(testSubArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3300 RUN_BINARY(testSubImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3301 RUN_BINARY(testSubImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3302 RUN_UNARY(testSubArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
3303 RUN_BINARY(testSubArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3304 RUN_BINARY(testSubArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3305}
3306
3307void addCallTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks)
3308{
3309 RUN(testCallSimple(1, 2));
3310 RUN(testCallRare(1, 2));
3311 RUN(testCallRareLive(1, 2, 3));
3312 RUN(testCallSimplePure(1, 2));
3313 RUN(testCallFunctionWithHellaArguments());
3314 RUN(testCallFunctionWithHellaArguments2());
3315 RUN(testCallFunctionWithHellaArguments3());
3316
3317 RUN(testReturnDouble(0.0));
3318 RUN(testReturnDouble(negativeZero()));
3319 RUN(testReturnDouble(42.5));
3320 RUN_UNARY(testReturnFloat, floatingPointOperands<float>());
3321
3322 RUN(testCallSimpleDouble(1, 2));
3323 RUN(testCallFunctionWithHellaDoubleArguments());
3324 RUN_BINARY(testCallSimpleFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3325 RUN(testCallFunctionWithHellaFloatArguments());
3326}
3327
3328void addShrTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks)
3329{
3330 RUN(testSShrArgs(1, 0));
3331 RUN(testSShrArgs(1, 1));
3332 RUN(testSShrArgs(1, 62));
3333 RUN(testSShrArgs(0xffffffffffffffff, 0));
3334 RUN(testSShrArgs(0xffffffffffffffff, 1));
3335 RUN(testSShrArgs(0xffffffffffffffff, 63));
3336 RUN(testSShrImms(1, 0));
3337 RUN(testSShrImms(1, 1));
3338 RUN(testSShrImms(1, 62));
3339 RUN(testSShrImms(1, 65));
3340 RUN(testSShrImms(0xffffffffffffffff, 0));
3341 RUN(testSShrImms(0xffffffffffffffff, 1));
3342 RUN(testSShrImms(0xffffffffffffffff, 63));
3343 RUN(testSShrArgImm(1, 0));
3344 RUN(testSShrArgImm(1, 1));
3345 RUN(testSShrArgImm(1, 62));
3346 RUN(testSShrArgImm(1, 65));
3347 RUN(testSShrArgImm(0xffffffffffffffff, 0));
3348 RUN(testSShrArgImm(0xffffffffffffffff, 1));
3349 RUN(testSShrArgImm(0xffffffffffffffff, 63));
3350 RUN(testSShrArg32(32));
3351 RUN(testSShrArgs32(1, 0));
3352 RUN(testSShrArgs32(1, 1));
3353 RUN(testSShrArgs32(1, 62));
3354 RUN(testSShrArgs32(1, 33));
3355 RUN(testSShrArgs32(0xffffffff, 0));
3356 RUN(testSShrArgs32(0xffffffff, 1));
3357 RUN(testSShrArgs32(0xffffffff, 63));
3358 RUN(testSShrImms32(1, 0));
3359 RUN(testSShrImms32(1, 1));
3360 RUN(testSShrImms32(1, 62));
3361 RUN(testSShrImms32(1, 33));
3362 RUN(testSShrImms32(0xffffffff, 0));
3363 RUN(testSShrImms32(0xffffffff, 1));
3364 RUN(testSShrImms32(0xffffffff, 63));
3365 RUN(testSShrArgImm32(1, 0));
3366 RUN(testSShrArgImm32(1, 1));
3367 RUN(testSShrArgImm32(1, 62));
3368 RUN(testSShrArgImm32(0xffffffff, 0));
3369 RUN(testSShrArgImm32(0xffffffff, 1));
3370 RUN(testSShrArgImm32(0xffffffff, 63));
3371
3372 RUN(testZShrArgs(1, 0));
3373 RUN(testZShrArgs(1, 1));
3374 RUN(testZShrArgs(1, 62));
3375 RUN(testZShrArgs(0xffffffffffffffff, 0));
3376 RUN(testZShrArgs(0xffffffffffffffff, 1));
3377 RUN(testZShrArgs(0xffffffffffffffff, 63));
3378 RUN(testZShrImms(1, 0));
3379 RUN(testZShrImms(1, 1));
3380 RUN(testZShrImms(1, 62));
3381 RUN(testZShrImms(1, 65));
3382 RUN(testZShrImms(0xffffffffffffffff, 0));
3383 RUN(testZShrImms(0xffffffffffffffff, 1));
3384 RUN(testZShrImms(0xffffffffffffffff, 63));
3385 RUN(testZShrArgImm(1, 0));
3386 RUN(testZShrArgImm(1, 1));
3387 RUN(testZShrArgImm(1, 62));
3388 RUN(testZShrArgImm(1, 65));
3389 RUN(testZShrArgImm(0xffffffffffffffff, 0));
3390 RUN(testZShrArgImm(0xffffffffffffffff, 1));
3391 RUN(testZShrArgImm(0xffffffffffffffff, 63));
3392 RUN(testZShrArg32(32));
3393 RUN(testZShrArgs32(1, 0));
3394 RUN(testZShrArgs32(1, 1));
3395 RUN(testZShrArgs32(1, 62));
3396 RUN(testZShrArgs32(1, 33));
3397 RUN(testZShrArgs32(0xffffffff, 0));
3398 RUN(testZShrArgs32(0xffffffff, 1));
3399 RUN(testZShrArgs32(0xffffffff, 63));
3400 RUN(testZShrImms32(1, 0));
3401 RUN(testZShrImms32(1, 1));
3402 RUN(testZShrImms32(1, 62));
3403 RUN(testZShrImms32(1, 33));
3404 RUN(testZShrImms32(0xffffffff, 0));
3405 RUN(testZShrImms32(0xffffffff, 1));
3406 RUN(testZShrImms32(0xffffffff, 63));
3407 RUN(testZShrArgImm32(1, 0));
3408 RUN(testZShrArgImm32(1, 1));
3409 RUN(testZShrArgImm32(1, 62));
3410 RUN(testZShrArgImm32(0xffffffff, 0));
3411 RUN(testZShrArgImm32(0xffffffff, 1));
3412 RUN(testZShrArgImm32(0xffffffff, 63));
3413}
3414
3415#endif // ENABLE(B3_JIT)
3416