bc61b54c590491ac6a2a9d2f82c5dc09641ca2ae
[WebKit-https.git] / Source / JavaScriptCore / b3 / testb3_2.cpp
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
31 void 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
41 void 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
55 void 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
73 void 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
107 void testLoadOffsetImm9Max()
108 {
109     testLoadWithOffsetImpl(255, 255);
110 }
111
112 void testLoadOffsetImm9MaxPlusOne()
113 {
114     testLoadWithOffsetImpl(256, 256);
115 }
116
117 void testLoadOffsetImm9MaxPlusTwo()
118 {
119     testLoadWithOffsetImpl(257, 257);
120 }
121
122 void testLoadOffsetImm9Min()
123 {
124     testLoadWithOffsetImpl(-256, -256);
125 }
126
127 void testLoadOffsetImm9MinMinusOne()
128 {
129     testLoadWithOffsetImpl(-257, -257);
130 }
131
132 void testLoadOffsetScaledUnsignedImm12Max()
133 {
134     testLoadWithOffsetImpl(32760, 16380);
135 }
136
137 void testLoadOffsetScaledUnsignedOverImm12Max()
138 {
139     testLoadWithOffsetImpl(32760, 32760);
140     testLoadWithOffsetImpl(32761, 16381);
141     testLoadWithOffsetImpl(32768, 16384);
142 }
143
144 static 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
159 static 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
173 static 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
188 void 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
212 void 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
236 static 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
253 static 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
270 void 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
281 void 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
292 void testReturnVoid()
293 {
294     Procedure proc;
295     BasicBlock* root = proc.addBlock();
296     root->appendNewControlValue(proc, Return, Origin());
297     compileAndRun<void>(proc);
298 }
299
300 void 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
312 void 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
326 void 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
340 void 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
354 void 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
371 void 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
385 void 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
402 void 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
415 void 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
433 void 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
450 void 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
464 void 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
481 void 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
496 void 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
511 void 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
530 void 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
550 void 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
562 void 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
575 void 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
588 void 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
601 void 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
614 void 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
629 void 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
646 void 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
660 void 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
675 void 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
690 void 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
703 void 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
719 void 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
739 void 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
763 void 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
789 void 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
802 void 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
830 void 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
847 void 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
861 void 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
874 void 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
887 void 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
901 void 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
915 void 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
933 void 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
955 void 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
974 void 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
994 void 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
1018 void 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
1042 void 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
1069 void 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
1096 void 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
1120 void 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
1144 void 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
1171 void 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
1198 void 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
1220 void 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
1244 void 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
1256 void 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
1269 void 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
1282 void 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
1295 void 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
1308 void 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
1323 void 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
1340 void 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
1355 void 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
1370 void 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
1383 void 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
1399 void 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
1419 void 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
1443 void 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
1455 void 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
1468 void 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
1481 void 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
1494 void 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
1507 void 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
1522 void 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
1539 void 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
1554 void 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
1569 void 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
1582 void 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
1594 void 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
1607 void 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
1620 void 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
1633 void 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
1646 void 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
1661 void 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
1678 void 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
1693 void 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
1708 void 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
1721 void 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
1737 void 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
1757 void 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
1781 void 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
1799 void 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
1815 void 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
1833 void 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
1849 void 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
1861 void 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
1875 void 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
1889 void 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
1904 void 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
1919 void 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
1934 void 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
1950 void 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
1966 void 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
1982 void 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
1997 void 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
2011 void 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
2025 void 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
2042 void 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
2059 void 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
2077 void 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
2095 void 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
2111 void 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
2127 void 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
2144 void 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
2158 void 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
2175 void 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
2192 void 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
2208 void 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
2221 void 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
2247 void 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
2259 void 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
2272 void 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
2285 void 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
2298 void 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
2311 void 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
2326 void 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
2343 void 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
2358 void 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
2373 void 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
2386 void 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
2402 void 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
2422 void 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
2446 void 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
2479 void 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
2492 void 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
2506 void 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
2521 static 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
2535 static 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
2550 static 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
2568 static void testBitAndNotImm(int64_t a, int64_t b)
2569 {
2570     Procedure proc;
2571     BasicBlock* root = proc.addBlock();
2572     Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2573     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
2574     Value* cstB = root->appendNew<Const64Value>(proc, Origin(), b);
2575     root->appendNewControlValue(
2576         proc, Return, Origin(),
2577         root->appendNew<Value>(
2578             proc, BitAnd, Origin(),
2579             notA,
2580             cstB));
2581
2582     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a & b));
2583 }
2584
2585 static void testBitAndImms(int64_t a, int64_t b)
2586 {
2587     Procedure proc;
2588     BasicBlock* root = proc.addBlock();
2589     root->appendNewControlValue(
2590         proc, Return, Origin(),
2591         root->appendNew<Value>(
2592             proc, BitAnd, Origin(),
2593             root->appendNew<Const64Value>(proc, Origin(), a),
2594             root->appendNew<Const64Value>(proc, Origin(), b)));
2595
2596     CHECK(compileAndRun<int64_t>(proc) == (a & b));
2597 }
2598
2599 static void testBitAndArgImm(int64_t a, int64_t b)
2600 {
2601     Procedure proc;
2602     BasicBlock* root = proc.addBlock();
2603     root->appendNewControlValue(
2604         proc, Return, Origin(),
2605         root->appendNew<Value>(
2606             proc, BitAnd, Origin(),
2607             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2608             root->appendNew<Const64Value>(proc, Origin(), b)));
2609
2610     CHECK(compileAndRun<int64_t>(proc, a) == (a & b));
2611 }
2612
2613 static void testBitAndImmArg(int64_t a, int64_t b)
2614 {
2615     Procedure proc;
2616     BasicBlock* root = proc.addBlock();
2617     root->appendNewControlValue(
2618         proc, Return, Origin(),
2619         root->appendNew<Value>(
2620             proc, BitAnd, Origin(),
2621             root->appendNew<Const64Value>(proc, Origin(), a),
2622             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2623
2624     CHECK(compileAndRun<int64_t>(proc, b) == (a & b));
2625 }
2626
2627 static void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c)
2628 {
2629     Procedure proc;
2630     BasicBlock* root = proc.addBlock();
2631     Value* innerBitAnd = root->appendNew<Value>(
2632         proc, BitAnd, Origin(),
2633         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2634         root->appendNew<Const64Value>(proc, Origin(), b));
2635     root->appendNewControlValue(
2636         proc, Return, Origin(),
2637         root->appendNew<Value>(
2638             proc, BitAnd, Origin(),
2639             innerBitAnd,
2640             root->appendNew<Const64Value>(proc, Origin(), c)));
2641
2642     CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c));
2643 }
2644
2645 static void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c)
2646 {
2647     Procedure proc;
2648     BasicBlock* root = proc.addBlock();
2649     Value* innerBitAnd = root->appendNew<Value>(
2650         proc, BitAnd, Origin(),
2651         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2652         root->appendNew<Const64Value>(proc, Origin(), c));
2653     root->appendNewControlValue(
2654         proc, Return, Origin(),
2655         root->appendNew<Value>(
2656             proc, BitAnd, Origin(),
2657             root->appendNew<Const64Value>(proc, Origin(), a),
2658             innerBitAnd));
2659
2660     CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c)));
2661 }
2662
2663 static void testBitAndArgs32(int a, int b)
2664 {
2665     Procedure proc;
2666     BasicBlock* root = proc.addBlock();
2667     root->appendNewControlValue(
2668         proc, Return, Origin(),
2669         root->appendNew<Value>(
2670             proc, BitAnd, Origin(),
2671             root->appendNew<Value>(
2672                 proc, Trunc, Origin(),
2673                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2674             root->appendNew<Value>(
2675                 proc, Trunc, Origin(),
2676                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2677
2678     CHECK(compileAndRun<int>(proc, a, b) == (a & b));
2679 }
2680
2681 static void testBitAndSameArg32(int a)
2682 {
2683     Procedure proc;
2684     BasicBlock* root = proc.addBlock();
2685     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2686         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2687     root->appendNewControlValue(
2688         proc, Return, Origin(),
2689         root->appendNew<Value>(
2690             proc, BitAnd, Origin(),
2691             argument,
2692             argument));
2693
2694     CHECK(compileAndRun<int>(proc, a) == a);
2695 }
2696
2697 static void testBitAndImms32(int a, int b)
2698 {
2699     Procedure proc;
2700     BasicBlock* root = proc.addBlock();
2701     root->appendNewControlValue(
2702         proc, Return, Origin(),
2703         root->appendNew<Value>(
2704             proc, BitAnd, Origin(),
2705             root->appendNew<Const32Value>(proc, Origin(), a),
2706             root->appendNew<Const32Value>(proc, Origin(), b)));
2707
2708     CHECK(compileAndRun<int>(proc) == (a & b));
2709 }
2710
2711 static void testBitAndArgImm32(int a, int b)
2712 {
2713     Procedure proc;
2714     BasicBlock* root = proc.addBlock();
2715     root->appendNewControlValue(
2716         proc, Return, Origin(),
2717         root->appendNew<Value>(
2718             proc, BitAnd, Origin(),
2719             root->appendNew<Value>(
2720                 proc, Trunc, Origin(),
2721                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2722             root->appendNew<Const32Value>(proc, Origin(), b)));
2723
2724     CHECK(compileAndRun<int>(proc, a) == (a & b));
2725 }
2726
2727 static void testBitAndImmArg32(int a, int b)
2728 {
2729     Procedure proc;
2730     BasicBlock* root = proc.addBlock();
2731     root->appendNewControlValue(
2732         proc, Return, Origin(),
2733         root->appendNew<Value>(
2734             proc, BitAnd, Origin(),
2735             root->appendNew<Const32Value>(proc, Origin(), a),
2736             root->appendNew<Value>(
2737                 proc, Trunc, Origin(),
2738                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2739
2740     CHECK(compileAndRun<int>(proc, b) == (a & b));
2741 }
2742
2743 static void testBitAndBitAndArgImmImm32(int a, int b, int c)
2744 {
2745     Procedure proc;
2746     BasicBlock* root = proc.addBlock();
2747     Value* innerBitAnd = root->appendNew<Value>(
2748         proc, BitAnd, Origin(),
2749         root->appendNew<Value>(
2750             proc, Trunc, Origin(),
2751             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2752         root->appendNew<Const32Value>(proc, Origin(), b));
2753     root->appendNewControlValue(
2754         proc, Return, Origin(),
2755         root->appendNew<Value>(
2756             proc, BitAnd, Origin(),
2757             innerBitAnd,
2758             root->appendNew<Const32Value>(proc, Origin(), c)));
2759
2760     CHECK(compileAndRun<int>(proc, a) == ((a & b) & c));
2761 }
2762
2763 static void testBitAndImmBitAndArgImm32(int a, int b, int c)
2764 {
2765     Procedure proc;
2766     BasicBlock* root = proc.addBlock();
2767     Value* innerBitAnd = root->appendNew<Value>(
2768         proc, BitAnd, Origin(),
2769         root->appendNew<Value>(
2770             proc, Trunc, Origin(),
2771             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2772         root->appendNew<Const32Value>(proc, Origin(), c));
2773     root->appendNewControlValue(
2774         proc, Return, Origin(),
2775         root->appendNew<Value>(
2776             proc, BitAnd, Origin(),
2777             root->appendNew<Const32Value>(proc, Origin(), a),
2778             innerBitAnd));
2779
2780     CHECK(compileAndRun<int>(proc, b) == (a & (b & c)));
2781 }
2782
2783 static void testBitAndWithMaskReturnsBooleans(int64_t a, int64_t b)
2784 {
2785     Procedure proc;
2786     BasicBlock* root = proc.addBlock();
2787     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2788     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2789     Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg0, arg1);
2790     Value* maskedEqual = root->appendNew<Value>(proc, BitAnd, Origin(),
2791         root->appendNew<Const32Value>(proc, Origin(), 0x5),
2792         equal);
2793     Value* inverted = root->appendNew<Value>(proc, BitXor, Origin(),
2794         root->appendNew<Const32Value>(proc, Origin(), 0x1),
2795         maskedEqual);
2796     Value* select = root->appendNew<Value>(proc, Select, Origin(), inverted,
2797         root->appendNew<Const64Value>(proc, Origin(), 42),
2798         root->appendNew<Const64Value>(proc, Origin(), -5));
2799
2800     root->appendNewControlValue(proc, Return, Origin(), select);
2801
2802     int64_t expected = (a == b) ? -5 : 42;
2803     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
2804 }
2805
2806 static double bitAndDouble(double a, double b)
2807 {
2808     return bitwise_cast<double>(bitwise_cast<uint64_t>(a) & bitwise_cast<uint64_t>(b));
2809 }
2810
2811 static void testBitAndArgDouble(double a)
2812 {
2813     Procedure proc;
2814     BasicBlock* root = proc.addBlock();
2815     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2816     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2817     root->appendNewControlValue(proc, Return, Origin(), result);
2818
2819     CHECK(isIdentical(compileAndRun<double>(proc, a), bitAndDouble(a, a)));
2820 }
2821
2822 static void testBitAndArgsDouble(double a, double b)
2823 {
2824     Procedure proc;
2825     BasicBlock* root = proc.addBlock();
2826     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2827     Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2828     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2829     root->appendNewControlValue(proc, Return, Origin(), result);
2830
2831     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2832 }
2833
2834 static void testBitAndArgImmDouble(double a, double b)
2835 {
2836     Procedure proc;
2837     BasicBlock* root = proc.addBlock();
2838     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2839     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2840     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2841     root->appendNewControlValue(proc, Return, Origin(), result);
2842
2843     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2844 }
2845
2846 static void testBitAndImmsDouble(double a, double b)
2847 {
2848     Procedure proc;
2849     BasicBlock* root = proc.addBlock();
2850     Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2851     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2852     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2853     root->appendNewControlValue(proc, Return, Origin(), result);
2854
2855     CHECK(isIdentical(compileAndRun<double>(proc), bitAndDouble(a, b)));
2856 }
2857
2858 static float bitAndFloat(float a, float b)
2859 {
2860     return bitwise_cast<float>(bitwise_cast<uint32_t>(a) & bitwise_cast<uint32_t>(b));
2861 }
2862
2863 static void testBitAndArgFloat(float a)
2864 {
2865     Procedure proc;
2866     BasicBlock* root = proc.addBlock();
2867     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2868         root->appendNew<Value>(proc, Trunc, Origin(),
2869             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2870     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2871     root->appendNewControlValue(proc, Return, Origin(), result);
2872
2873     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitAndFloat(a, a)));
2874 }
2875
2876 static void testBitAndArgsFloat(float a, float b)
2877 {
2878     Procedure proc;
2879     BasicBlock* root = proc.addBlock();
2880     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2881         root->appendNew<Value>(proc, Trunc, Origin(),
2882             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2883     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2884         root->appendNew<Value>(proc, Trunc, Origin(),
2885             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2886     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2887     root->appendNewControlValue(proc, Return, Origin(), result);
2888
2889     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2890 }
2891
2892 static void testBitAndArgImmFloat(float a, float b)
2893 {
2894     Procedure proc;
2895     BasicBlock* root = proc.addBlock();
2896     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2897         root->appendNew<Value>(proc, Trunc, Origin(),
2898             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2899     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2900     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2901     root->appendNewControlValue(proc, Return, Origin(), result);
2902
2903     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2904 }
2905
2906 static void testBitAndImmsFloat(float a, float b)
2907 {
2908     Procedure proc;
2909     BasicBlock* root = proc.addBlock();
2910     Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2911     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2912     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2913     root->appendNewControlValue(proc, Return, Origin(), result);
2914
2915     CHECK(isIdentical(compileAndRun<float>(proc), bitAndFloat(a, b)));
2916 }
2917
2918 static void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b)
2919 {
2920     Procedure proc;
2921     BasicBlock* root = proc.addBlock();
2922     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2923         root->appendNew<Value>(proc, Trunc, Origin(),
2924             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2925     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2926         root->appendNew<Value>(proc, Trunc, Origin(),
2927             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2928     Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
2929     Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
2930     Value* doubleResult = root->appendNew<Value>(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble);
2931     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
2932     root->appendNewControlValue(proc, Return, Origin(), floatResult);
2933
2934     double doubleA = a;
2935     double doubleB = b;
2936     float expected = static_cast<float>(bitAndDouble(doubleA, doubleB));
2937     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
2938 }
2939
2940 static void testBitOrArgs(int64_t a, int64_t b)
2941 {
2942     Procedure proc;
2943     BasicBlock* root = proc.addBlock();
2944     root->appendNewControlValue(
2945         proc, Return, Origin(),
2946         root->appendNew<Value>(
2947             proc, BitOr, Origin(),
2948             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2949             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2950
2951     CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b));
2952 }
2953
2954 static void testBitOrSameArg(int64_t a)
2955 {
2956     Procedure proc;
2957     BasicBlock* root = proc.addBlock();
2958     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2959     root->appendNewControlValue(
2960         proc, Return, Origin(),
2961         root->appendNew<Value>(
2962             proc, BitOr, Origin(),
2963             argument,
2964             argument));
2965
2966     CHECK(compileAndRun<int64_t>(proc, a) == a);
2967 }
2968
2969 static void testBitOrAndAndArgs(int64_t a, int64_t b, int64_t c)
2970 {
2971     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
2972     // ((a & b) | (a & c))
2973     // ((a & b) | (c & a))
2974     // ((b & a) | (a & c))
2975     // ((b & a) | (c & a))
2976     for (int i = 0; i < 4; ++i) {
2977         Procedure proc;
2978         BasicBlock* root = proc.addBlock();
2979         Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2980         Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2981         Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2982         Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
2983             : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
2984         Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
2985             : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
2986         root->appendNewControlValue(
2987             proc, Return, Origin(),
2988             root->appendNew<Value>(
2989                 proc, BitOr, Origin(),
2990                 andAB,
2991                 andAC));
2992
2993         CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a & b) | (a & c)));
2994     }
2995 }
2996
2997 static void testBitOrAndSameArgs(int64_t a, int64_t b)
2998 {
2999     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3000     // ((a & b) | a)
3001     // ((b & a) | a)
3002     // (a | (a & b))
3003     // (a | (b & a))
3004     for (int i = 0; i < 4; ++i) {
3005         Procedure proc;
3006         BasicBlock* root = proc.addBlock();
3007         Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3008         Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3009         Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3010             : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3011         Value* result = i & 2 ? root->appendNew<Value>(proc, BitOr, Origin(), andAB, argA)
3012             : root->appendNew<Value>(proc, BitOr, Origin(), argA, andAB);
3013         root->appendNewControlValue(proc, Return, Origin(), result);
3014
3015         CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a & b) | a));
3016     }
3017 }
3018
3019 static void testBitOrNotNot(int64_t a, int64_t b)
3020 {
3021     Procedure proc;
3022     BasicBlock* root = proc.addBlock();
3023     Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3024     Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3025     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
3026     Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const64Value>(proc, Origin(), -1));
3027     root->appendNewControlValue(
3028         proc, Return, Origin(),
3029         root->appendNew<Value>(
3030             proc, BitOr, Origin(),
3031             notA,
3032             notB));
3033
3034     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | ~b));
3035 }
3036
3037 static void testBitOrNotImm(int64_t a, int64_t b)
3038 {
3039     Procedure proc;
3040     BasicBlock* root = proc.addBlock();
3041     Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3042     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
3043     Value* cstB = root->appendNew<Const64Value>(proc, Origin(), b);
3044     root->appendNewControlValue(
3045         proc, Return, Origin(),
3046         root->appendNew<Value>(
3047             proc, BitOr, Origin(),
3048             notA,
3049             cstB));
3050
3051     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | b));
3052 }
3053
3054 static void testBitOrImms(int64_t a, int64_t b)
3055 {
3056     Procedure proc;
3057     BasicBlock* root = proc.addBlock();
3058     root->appendNewControlValue(
3059         proc, Return, Origin(),
3060         root->appendNew<Value>(
3061             proc, BitOr, Origin(),
3062             root->appendNew<Const64Value>(proc, Origin(), a),
3063             root->appendNew<Const64Value>(proc, Origin(), b)));
3064
3065     CHECK(compileAndRun<int64_t>(proc) == (a | b));
3066 }
3067
3068 static void testBitOrArgImm(int64_t a, int64_t b)
3069 {
3070     Procedure proc;
3071     BasicBlock* root = proc.addBlock();
3072     root->appendNewControlValue(
3073         proc, Return, Origin(),
3074         root->appendNew<Value>(
3075             proc, BitOr, Origin(),
3076             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3077             root->appendNew<Const64Value>(proc, Origin(), b)));
3078
3079     CHECK(compileAndRun<int64_t>(proc, a) == (a | b));
3080 }
3081
3082 static void testBitOrImmArg(int64_t a, int64_t b)
3083 {
3084     Procedure proc;
3085     BasicBlock* root = proc.addBlock();
3086     root->appendNewControlValue(
3087         proc, Return, Origin(),
3088         root->appendNew<Value>(
3089             proc, BitOr, Origin(),
3090             root->appendNew<Const64Value>(proc, Origin(), a),
3091             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3092
3093     CHECK(compileAndRun<int64_t>(proc, b) == (a | b));
3094 }
3095
3096 static void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c)
3097 {
3098     Procedure proc;
3099     BasicBlock* root = proc.addBlock();
3100     Value* innerBitOr = root->appendNew<Value>(
3101         proc, BitOr, Origin(),
3102         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3103         root->appendNew<Const64Value>(proc, Origin(), b));
3104     root->appendNewControlValue(
3105         proc, Return, Origin(),
3106         root->appendNew<Value>(
3107             proc, BitOr, Origin(),
3108             innerBitOr,
3109             root->appendNew<Const64Value>(proc, Origin(), c)));
3110
3111     CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c));
3112 }
3113
3114 static void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c)
3115 {
3116     Procedure proc;
3117     BasicBlock* root = proc.addBlock();
3118     Value* innerBitOr = root->appendNew<Value>(
3119         proc, BitOr, Origin(),
3120         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3121         root->appendNew<Const64Value>(proc, Origin(), c));
3122     root->appendNewControlValue(
3123         proc, Return, Origin(),
3124         root->appendNew<Value>(
3125             proc, BitOr, Origin(),
3126             root->appendNew<Const64Value>(proc, Origin(), a),
3127             innerBitOr));
3128
3129     CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c)));
3130 }
3131
3132 static void testBitOrArgs32(int a, int b)
3133 {
3134     Procedure proc;
3135     BasicBlock* root = proc.addBlock();
3136     root->appendNewControlValue(
3137         proc, Return, Origin(),
3138         root->appendNew<Value>(
3139             proc, BitOr, Origin(),
3140             root->appendNew<Value>(
3141                 proc, Trunc, Origin(),
3142                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3143             root->appendNew<Value>(
3144                 proc, Trunc, Origin(),
3145                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3146
3147     CHECK(compileAndRun<int>(proc, a, b) == (a | b));
3148 }
3149
3150 static void testBitOrSameArg32(int a)
3151 {
3152     Procedure proc;
3153     BasicBlock* root = proc.addBlock();
3154     Value* argument = root->appendNew<Value>(
3155         proc, Trunc, Origin(),
3156             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3157     root->appendNewControlValue(
3158         proc, Return, Origin(),
3159         root->appendNew<Value>(
3160             proc, BitOr, Origin(),
3161             argument,
3162             argument));
3163
3164     CHECK(compileAndRun<int>(proc, a) == a);
3165 }
3166
3167 static void testBitOrImms32(int a, int b)
3168 {
3169     Procedure proc;
3170     BasicBlock* root = proc.addBlock();
3171     root->appendNewControlValue(
3172         proc, Return, Origin(),
3173         root->appendNew<Value>(
3174             proc, BitOr, Origin(),
3175             root->appendNew<Const32Value>(proc, Origin(), a),
3176             root->appendNew<Const32Value>(proc, Origin(), b)));
3177
3178     CHECK(compileAndRun<int>(proc) == (a | b));
3179 }
3180
3181 static void testBitOrArgImm32(int a, int b)
3182 {
3183     Procedure proc;
3184     BasicBlock* root = proc.addBlock();
3185     root->appendNewControlValue(
3186         proc, Return, Origin(),
3187         root->appendNew<Value>(
3188             proc, BitOr, Origin(),
3189             root->appendNew<Value>(
3190                 proc, Trunc, Origin(),
3191                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3192             root->appendNew<Const32Value>(proc, Origin(), b)));
3193
3194     CHECK(compileAndRun<int>(proc, a) == (a | b));
3195 }
3196
3197 static void testBitOrImmArg32(int a, int b)
3198 {
3199     Procedure proc;
3200     BasicBlock* root = proc.addBlock();
3201     root->appendNewControlValue(
3202         proc, Return, Origin(),
3203         root->appendNew<Value>(
3204             proc, BitOr, Origin(),
3205             root->appendNew<Const32Value>(proc, Origin(), a),
3206             root->appendNew<Value>(
3207                 proc, Trunc, Origin(),
3208                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3209
3210     CHECK(compileAndRun<int>(proc, b) == (a | b));
3211 }
3212
3213 void addBitTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks)
3214 {
3215     RUN(testBitAndArgs(43, 43));
3216     RUN(testBitAndArgs(43, 0));
3217     RUN(testBitAndArgs(10, 3));
3218     RUN(testBitAndArgs(42, 0xffffffffffffffff));
3219     RUN(testBitAndSameArg(43));
3220     RUN(testBitAndSameArg(0));
3221     RUN(testBitAndSameArg(3));
3222     RUN(testBitAndSameArg(0xffffffffffffffff));
3223     RUN(testBitAndImms(43, 43));
3224     RUN(testBitAndImms(43, 0));
3225     RUN(testBitAndImms(10, 3));
3226     RUN(testBitAndImms(42, 0xffffffffffffffff));
3227     RUN(testBitAndArgImm(43, 43));
3228     RUN(testBitAndArgImm(43, 0));
3229     RUN(testBitAndArgImm(10, 3));
3230     RUN(testBitAndArgImm(42, 0xffffffffffffffff));
3231     RUN(testBitAndArgImm(42, 0xff));
3232     RUN(testBitAndArgImm(300, 0xff));
3233     RUN(testBitAndArgImm(-300, 0xff));
3234     RUN(testBitAndArgImm(42, 0xffff));
3235     RUN(testBitAndArgImm(40000, 0xffff));
3236     RUN(testBitAndArgImm(-40000, 0xffff));
3237     RUN(testBitAndImmArg(43, 43));
3238     RUN(testBitAndImmArg(43, 0));
3239     RUN(testBitAndImmArg(10, 3));
3240     RUN(testBitAndImmArg(42, 0xffffffffffffffff));
3241     RUN(testBitAndBitAndArgImmImm(2, 7, 3));
3242     RUN(testBitAndBitAndArgImmImm(1, 6, 6));
3243     RUN(testBitAndBitAndArgImmImm(0xffff, 24, 7));
3244     RUN(testBitAndImmBitAndArgImm(7, 2, 3));
3245     RUN(testBitAndImmBitAndArgImm(6, 1, 6));
3246     RUN(testBitAndImmBitAndArgImm(24, 0xffff, 7));
3247     RUN(testBitAndArgs32(43, 43));
3248     RUN(testBitAndArgs32(43, 0));
3249     RUN(testBitAndArgs32(10, 3));
3250     RUN(testBitAndArgs32(42, 0xffffffff));
3251     RUN(testBitAndSameArg32(43));
3252     RUN(testBitAndSameArg32(0));
3253     RUN(testBitAndSameArg32(3));
3254     RUN(testBitAndSameArg32(0xffffffff));
3255     RUN(testBitAndImms32(43, 43));
3256     RUN(testBitAndImms32(43, 0));
3257     RUN(testBitAndImms32(10, 3));
3258     RUN(testBitAndImms32(42, 0xffffffff));
3259     RUN(testBitAndArgImm32(43, 43));
3260     RUN(testBitAndArgImm32(43, 0));
3261     RUN(testBitAndArgImm32(10, 3));
3262     RUN(testBitAndArgImm32(42, 0xffffffff));
3263     RUN(testBitAndImmArg32(43, 43));
3264     RUN(testBitAndImmArg32(43, 0));
3265     RUN(testBitAndImmArg32(10, 3));
3266     RUN(testBitAndImmArg32(42, 0xffffffff));
3267     RUN(testBitAndImmArg32(42, 0xff));
3268     RUN(testBitAndImmArg32(300, 0xff));
3269     RUN(testBitAndImmArg32(-300, 0xff));
3270     RUN(testBitAndImmArg32(42, 0xffff));
3271     RUN(testBitAndImmArg32(40000, 0xffff));
3272     RUN(testBitAndImmArg32(-40000, 0xffff));
3273     RUN(testBitAndBitAndArgImmImm32(2, 7, 3));
3274     RUN(testBitAndBitAndArgImmImm32(1, 6, 6));
3275     RUN(testBitAndBitAndArgImmImm32(0xffff, 24, 7));
3276     RUN(testBitAndImmBitAndArgImm32(7, 2, 3));
3277     RUN(testBitAndImmBitAndArgImm32(6, 1, 6));
3278     RUN(testBitAndImmBitAndArgImm32(24, 0xffff, 7));
3279     RUN_BINARY(testBitAndWithMaskReturnsBooleans, int64Operands(), int64Operands());
3280     RUN_UNARY(testBitAndArgDouble, floatingPointOperands<double>());
3281     RUN_BINARY(testBitAndArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3282     RUN_BINARY(testBitAndArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3283     RUN_BINARY(testBitAndImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3284     RUN_UNARY(testBitAndArgFloat, floatingPointOperands<float>());
3285     RUN_BINARY(testBitAndArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3286     RUN_BINARY(testBitAndArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3287     RUN_BINARY(testBitAndImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3288     RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3289     RUN_BINARY(testBitAndNotNot, int64Operands(), int64Operands());
3290     RUN_BINARY(testBitAndNotImm, int64Operands(), int64Operands());
3291     
3292     RUN(testBitOrArgs(43, 43));
3293     RUN(testBitOrArgs(43, 0));
3294     RUN(testBitOrArgs(10, 3));
3295     RUN(testBitOrArgs(42, 0xffffffffffffffff));
3296     RUN(testBitOrSameArg(43));
3297     RUN(testBitOrSameArg(0));
3298     RUN(testBitOrSameArg(3));
3299     RUN(testBitOrSameArg(0xffffffffffffffff));
3300     RUN(testBitOrImms(43, 43));
3301     RUN(testBitOrImms(43, 0));
3302     RUN(testBitOrImms(10, 3));
3303     RUN(testBitOrImms(42, 0xffffffffffffffff));
3304     RUN(testBitOrArgImm(43, 43));
3305     RUN(testBitOrArgImm(43, 0));
3306     RUN(testBitOrArgImm(10, 3));
3307     RUN(testBitOrArgImm(42, 0xffffffffffffffff));
3308     RUN(testBitOrImmArg(43, 43));
3309     RUN(testBitOrImmArg(43, 0));
3310     RUN(testBitOrImmArg(10, 3));
3311     RUN(testBitOrImmArg(42, 0xffffffffffffffff));
3312     RUN(testBitOrBitOrArgImmImm(2, 7, 3));
3313     RUN(testBitOrBitOrArgImmImm(1, 6, 6));
3314     RUN(testBitOrBitOrArgImmImm(0xffff, 24, 7));
3315     RUN(testBitOrImmBitOrArgImm(7, 2, 3));
3316     RUN(testBitOrImmBitOrArgImm(6, 1, 6));
3317     RUN(testBitOrImmBitOrArgImm(24, 0xffff, 7));
3318     RUN(testBitOrArgs32(43, 43));
3319     RUN(testBitOrArgs32(43, 0));
3320     RUN(testBitOrArgs32(10, 3));
3321     RUN(testBitOrArgs32(42, 0xffffffff));
3322     RUN(testBitOrSameArg32(43));
3323     RUN(testBitOrSameArg32(0));
3324     RUN(testBitOrSameArg32(3));
3325     RUN(testBitOrSameArg32(0xffffffff));
3326     RUN(testBitOrImms32(43, 43));
3327     RUN(testBitOrImms32(43, 0));
3328     RUN(testBitOrImms32(10, 3));
3329     RUN(testBitOrImms32(42, 0xffffffff));
3330     RUN(testBitOrArgImm32(43, 43));
3331     RUN(testBitOrArgImm32(43, 0));
3332     RUN(testBitOrArgImm32(10, 3));
3333     RUN(testBitOrArgImm32(42, 0xffffffff));
3334     RUN(testBitOrImmArg32(43, 43));
3335     RUN(testBitOrImmArg32(43, 0));
3336     RUN(testBitOrImmArg32(10, 3));
3337     RUN(testBitOrImmArg32(42, 0xffffffff));
3338     RUN(testBitOrBitOrArgImmImm32(2, 7, 3));
3339     RUN(testBitOrBitOrArgImmImm32(1, 6, 6));
3340     RUN(testBitOrBitOrArgImmImm32(0xffff, 24, 7));
3341     RUN(testBitOrImmBitOrArgImm32(7, 2, 3));
3342     RUN(testBitOrImmBitOrArgImm32(6, 1, 6));
3343     RUN(testBitOrImmBitOrArgImm32(24, 0xffff, 7));
3344     RUN_UNARY(testBitOrArgDouble, floatingPointOperands<double>());
3345     RUN_BINARY(testBitOrArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3346     RUN_BINARY(testBitOrArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3347     RUN_BINARY(testBitOrImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3348     RUN_UNARY(testBitOrArgFloat, floatingPointOperands<float>());
3349     RUN_BINARY(testBitOrArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3350     RUN_BINARY(testBitOrArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3351     RUN_BINARY(testBitOrImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3352     RUN_BINARY(testBitOrArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3353     RUN_TERNARY(testBitOrAndAndArgs, int64Operands(), int64Operands(), int64Operands());
3354     RUN_BINARY(testBitOrAndSameArgs, int64Operands(), int64Operands());
3355     RUN_BINARY(testBitOrNotNot, int64Operands(), int64Operands());
3356     RUN_BINARY(testBitOrNotImm, int64Operands(), int64Operands());
3357     
3358     RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands());
3359     RUN_UNARY(testBitXorSameArg, int64Operands());
3360     RUN_BINARY(testBitXorImms, int64Operands(), int64Operands());
3361     RUN_BINARY(testBitXorArgImm, int64Operands(), int64Operands());
3362     RUN_BINARY(testBitXorImmArg, int64Operands(), int64Operands());
3363     RUN(testBitXorBitXorArgImmImm(2, 7, 3));
3364     RUN(testBitXorBitXorArgImmImm(1, 6, 6));
3365     RUN(testBitXorBitXorArgImmImm(0xffff, 24, 7));
3366     RUN(testBitXorImmBitXorArgImm(7, 2, 3));
3367     RUN(testBitXorImmBitXorArgImm(6, 1, 6));
3368     RUN(testBitXorImmBitXorArgImm(24, 0xffff, 7));
3369     RUN(testBitXorArgs32(43, 43));
3370     RUN(testBitXorArgs32(43, 0));
3371     RUN(testBitXorArgs32(10, 3));
3372     RUN(testBitXorArgs32(42, 0xffffffff));
3373     RUN(testBitXorSameArg32(43));
3374     RUN(testBitXorSameArg32(0));
3375     RUN(testBitXorSameArg32(3));
3376     RUN(testBitXorSameArg32(0xffffffff));
3377     RUN(testBitXorImms32(43, 43));
3378     RUN(testBitXorImms32(43, 0));
3379     RUN(testBitXorImms32(10, 3));
3380     RUN(testBitXorImms32(42, 0xffffffff));
3381     RUN(testBitXorArgImm32(43, 43));
3382     RUN(testBitXorArgImm32(43, 0));
3383     RUN(testBitXorArgImm32(10, 3));
3384     RUN(testBitXorArgImm32(42, 0xffffffff));
3385     RUN(testBitXorImmArg32(43, 43));
3386     RUN(testBitXorImmArg32(43, 0));
3387     RUN(testBitXorImmArg32(10, 3));
3388     RUN(testBitXorImmArg32(42, 0xffffffff));
3389     RUN(testBitXorBitXorArgImmImm32(2, 7, 3));
3390     RUN(testBitXorBitXorArgImmImm32(1, 6, 6));
3391     RUN(testBitXorBitXorArgImmImm32(0xffff, 24, 7));
3392     RUN(testBitXorImmBitXorArgImm32(7, 2, 3));
3393     RUN(testBitXorImmBitXorArgImm32(6, 1, 6));
3394     RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7));
3395     RUN_TERNARY(testBitXorAndAndArgs, int64Operands(), int64Operands(), int64Operands());
3396     RUN_BINARY(testBitXorAndSameArgs, int64Operands(), int64Operands());
3397     
3398     RUN_UNARY(testBitNotArg, int64Operands());
3399     RUN_UNARY(testBitNotImm, int64Operands());
3400     RUN_UNARY(testBitNotMem, int64Operands());
3401     RUN_UNARY(testBitNotArg32, int32Operands());
3402     RUN_UNARY(testBitNotImm32, int32Operands());
3403     RUN_UNARY(testBitNotMem32, int32Operands());
3404     RUN_BINARY(testNotOnBooleanAndBranch32, int32Operands(), int32Operands());
3405     RUN_BINARY(testBitNotOnBooleanAndBranch32, int32Operands(), int32Operands());
3406     
3407     RUN_BINARY(testBitXorTreeArgs, int64Operands(), int64Operands());
3408     RUN_BINARY(testBitXorTreeArgsEven, int64Operands(), int64Operands());
3409     RUN_BINARY(testBitXorTreeArgImm, int64Operands(), int64Operands());
3410     RUN_UNARY(testBitAndTreeArg32, int32Operands());
3411     RUN_UNARY(testBitOrTreeArg32, int32Operands());
3412 }
3413
3414 #endif // ENABLE(B3_JIT)