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