[JSC] 32bit bitwide operation with all-one (-1) is wrong in B3
[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 testBitAndNotNot32(int32_t a, int32_t b)
2569 {
2570     Procedure proc;
2571     BasicBlock* root = proc.addBlock();
2572     Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2573     Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2574     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
2575     Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const32Value>(proc, Origin(), -1));
2576     root->appendNewControlValue(
2577         proc, Return, Origin(),
2578         root->appendNew<Value>(
2579             proc, BitAnd, Origin(),
2580             notA,
2581             notB));
2582
2583     CHECK_EQ(compileAndRun<int32_t>(proc, a, b), (~a & ~b));
2584 }
2585
2586 static void testBitAndNotImm(int64_t a, int64_t b)
2587 {
2588     Procedure proc;
2589     BasicBlock* root = proc.addBlock();
2590     Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2591     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
2592     Value* cstB = root->appendNew<Const64Value>(proc, Origin(), b);
2593     root->appendNewControlValue(
2594         proc, Return, Origin(),
2595         root->appendNew<Value>(
2596             proc, BitAnd, Origin(),
2597             notA,
2598             cstB));
2599
2600     CHECK_EQ(compileAndRun<int64_t>(proc, a), (~a & b));
2601 }
2602
2603 static void testBitAndNotImm32(int32_t a, int32_t b)
2604 {
2605     Procedure proc;
2606     BasicBlock* root = proc.addBlock();
2607     Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2608     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
2609     Value* cstB = root->appendNew<Const32Value>(proc, Origin(), b);
2610     root->appendNewControlValue(
2611         proc, Return, Origin(),
2612         root->appendNew<Value>(
2613             proc, BitAnd, Origin(),
2614             notA,
2615             cstB));
2616
2617     CHECK_EQ(compileAndRun<int32_t>(proc, a), (~a & b));
2618 }
2619
2620 static void testBitAndImms(int64_t a, int64_t b)
2621 {
2622     Procedure proc;
2623     BasicBlock* root = proc.addBlock();
2624     root->appendNewControlValue(
2625         proc, Return, Origin(),
2626         root->appendNew<Value>(
2627             proc, BitAnd, Origin(),
2628             root->appendNew<Const64Value>(proc, Origin(), a),
2629             root->appendNew<Const64Value>(proc, Origin(), b)));
2630
2631     CHECK(compileAndRun<int64_t>(proc) == (a & b));
2632 }
2633
2634 static void testBitAndArgImm(int64_t a, int64_t b)
2635 {
2636     Procedure proc;
2637     BasicBlock* root = proc.addBlock();
2638     root->appendNewControlValue(
2639         proc, Return, Origin(),
2640         root->appendNew<Value>(
2641             proc, BitAnd, Origin(),
2642             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2643             root->appendNew<Const64Value>(proc, Origin(), b)));
2644
2645     CHECK(compileAndRun<int64_t>(proc, a) == (a & b));
2646 }
2647
2648 static void testBitAndImmArg(int64_t a, int64_t b)
2649 {
2650     Procedure proc;
2651     BasicBlock* root = proc.addBlock();
2652     root->appendNewControlValue(
2653         proc, Return, Origin(),
2654         root->appendNew<Value>(
2655             proc, BitAnd, Origin(),
2656             root->appendNew<Const64Value>(proc, Origin(), a),
2657             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2658
2659     CHECK(compileAndRun<int64_t>(proc, b) == (a & b));
2660 }
2661
2662 static void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c)
2663 {
2664     Procedure proc;
2665     BasicBlock* root = proc.addBlock();
2666     Value* innerBitAnd = root->appendNew<Value>(
2667         proc, BitAnd, Origin(),
2668         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2669         root->appendNew<Const64Value>(proc, Origin(), b));
2670     root->appendNewControlValue(
2671         proc, Return, Origin(),
2672         root->appendNew<Value>(
2673             proc, BitAnd, Origin(),
2674             innerBitAnd,
2675             root->appendNew<Const64Value>(proc, Origin(), c)));
2676
2677     CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c));
2678 }
2679
2680 static void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c)
2681 {
2682     Procedure proc;
2683     BasicBlock* root = proc.addBlock();
2684     Value* innerBitAnd = root->appendNew<Value>(
2685         proc, BitAnd, Origin(),
2686         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2687         root->appendNew<Const64Value>(proc, Origin(), c));
2688     root->appendNewControlValue(
2689         proc, Return, Origin(),
2690         root->appendNew<Value>(
2691             proc, BitAnd, Origin(),
2692             root->appendNew<Const64Value>(proc, Origin(), a),
2693             innerBitAnd));
2694
2695     CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c)));
2696 }
2697
2698 static void testBitAndArgs32(int a, int b)
2699 {
2700     Procedure proc;
2701     BasicBlock* root = proc.addBlock();
2702     root->appendNewControlValue(
2703         proc, Return, Origin(),
2704         root->appendNew<Value>(
2705             proc, BitAnd, Origin(),
2706             root->appendNew<Value>(
2707                 proc, Trunc, Origin(),
2708                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2709             root->appendNew<Value>(
2710                 proc, Trunc, Origin(),
2711                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2712
2713     CHECK(compileAndRun<int>(proc, a, b) == (a & b));
2714 }
2715
2716 static void testBitAndSameArg32(int a)
2717 {
2718     Procedure proc;
2719     BasicBlock* root = proc.addBlock();
2720     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2721         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2722     root->appendNewControlValue(
2723         proc, Return, Origin(),
2724         root->appendNew<Value>(
2725             proc, BitAnd, Origin(),
2726             argument,
2727             argument));
2728
2729     CHECK(compileAndRun<int>(proc, a) == a);
2730 }
2731
2732 static void testBitAndImms32(int a, int b)
2733 {
2734     Procedure proc;
2735     BasicBlock* root = proc.addBlock();
2736     root->appendNewControlValue(
2737         proc, Return, Origin(),
2738         root->appendNew<Value>(
2739             proc, BitAnd, Origin(),
2740             root->appendNew<Const32Value>(proc, Origin(), a),
2741             root->appendNew<Const32Value>(proc, Origin(), b)));
2742
2743     CHECK(compileAndRun<int>(proc) == (a & b));
2744 }
2745
2746 static void testBitAndArgImm32(int a, int b)
2747 {
2748     Procedure proc;
2749     BasicBlock* root = proc.addBlock();
2750     root->appendNewControlValue(
2751         proc, Return, Origin(),
2752         root->appendNew<Value>(
2753             proc, BitAnd, Origin(),
2754             root->appendNew<Value>(
2755                 proc, Trunc, Origin(),
2756                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2757             root->appendNew<Const32Value>(proc, Origin(), b)));
2758
2759     CHECK(compileAndRun<int>(proc, a) == (a & b));
2760 }
2761
2762 static void testBitAndImmArg32(int a, int b)
2763 {
2764     Procedure proc;
2765     BasicBlock* root = proc.addBlock();
2766     root->appendNewControlValue(
2767         proc, Return, Origin(),
2768         root->appendNew<Value>(
2769             proc, BitAnd, Origin(),
2770             root->appendNew<Const32Value>(proc, Origin(), a),
2771             root->appendNew<Value>(
2772                 proc, Trunc, Origin(),
2773                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2774
2775     CHECK(compileAndRun<int>(proc, b) == (a & b));
2776 }
2777
2778 static void testBitAndBitAndArgImmImm32(int a, int b, int c)
2779 {
2780     Procedure proc;
2781     BasicBlock* root = proc.addBlock();
2782     Value* innerBitAnd = root->appendNew<Value>(
2783         proc, BitAnd, Origin(),
2784         root->appendNew<Value>(
2785             proc, Trunc, Origin(),
2786             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2787         root->appendNew<Const32Value>(proc, Origin(), b));
2788     root->appendNewControlValue(
2789         proc, Return, Origin(),
2790         root->appendNew<Value>(
2791             proc, BitAnd, Origin(),
2792             innerBitAnd,
2793             root->appendNew<Const32Value>(proc, Origin(), c)));
2794
2795     CHECK(compileAndRun<int>(proc, a) == ((a & b) & c));
2796 }
2797
2798 static void testBitAndImmBitAndArgImm32(int a, int b, int c)
2799 {
2800     Procedure proc;
2801     BasicBlock* root = proc.addBlock();
2802     Value* innerBitAnd = root->appendNew<Value>(
2803         proc, BitAnd, Origin(),
2804         root->appendNew<Value>(
2805             proc, Trunc, Origin(),
2806             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2807         root->appendNew<Const32Value>(proc, Origin(), c));
2808     root->appendNewControlValue(
2809         proc, Return, Origin(),
2810         root->appendNew<Value>(
2811             proc, BitAnd, Origin(),
2812             root->appendNew<Const32Value>(proc, Origin(), a),
2813             innerBitAnd));
2814
2815     CHECK(compileAndRun<int>(proc, b) == (a & (b & c)));
2816 }
2817
2818 static void testBitAndWithMaskReturnsBooleans(int64_t a, int64_t b)
2819 {
2820     Procedure proc;
2821     BasicBlock* root = proc.addBlock();
2822     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2823     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2824     Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg0, arg1);
2825     Value* maskedEqual = root->appendNew<Value>(proc, BitAnd, Origin(),
2826         root->appendNew<Const32Value>(proc, Origin(), 0x5),
2827         equal);
2828     Value* inverted = root->appendNew<Value>(proc, BitXor, Origin(),
2829         root->appendNew<Const32Value>(proc, Origin(), 0x1),
2830         maskedEqual);
2831     Value* select = root->appendNew<Value>(proc, Select, Origin(), inverted,
2832         root->appendNew<Const64Value>(proc, Origin(), 42),
2833         root->appendNew<Const64Value>(proc, Origin(), -5));
2834
2835     root->appendNewControlValue(proc, Return, Origin(), select);
2836
2837     int64_t expected = (a == b) ? -5 : 42;
2838     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
2839 }
2840
2841 static double bitAndDouble(double a, double b)
2842 {
2843     return bitwise_cast<double>(bitwise_cast<uint64_t>(a) & bitwise_cast<uint64_t>(b));
2844 }
2845
2846 static void testBitAndArgDouble(double a)
2847 {
2848     Procedure proc;
2849     BasicBlock* root = proc.addBlock();
2850     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2851     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2852     root->appendNewControlValue(proc, Return, Origin(), result);
2853
2854     CHECK(isIdentical(compileAndRun<double>(proc, a), bitAndDouble(a, a)));
2855 }
2856
2857 static void testBitAndArgsDouble(double a, double b)
2858 {
2859     Procedure proc;
2860     BasicBlock* root = proc.addBlock();
2861     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2862     Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2863     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2864     root->appendNewControlValue(proc, Return, Origin(), result);
2865
2866     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2867 }
2868
2869 static void testBitAndArgImmDouble(double a, double b)
2870 {
2871     Procedure proc;
2872     BasicBlock* root = proc.addBlock();
2873     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2874     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2875     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2876     root->appendNewControlValue(proc, Return, Origin(), result);
2877
2878     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2879 }
2880
2881 static void testBitAndImmsDouble(double a, double b)
2882 {
2883     Procedure proc;
2884     BasicBlock* root = proc.addBlock();
2885     Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2886     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2887     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2888     root->appendNewControlValue(proc, Return, Origin(), result);
2889
2890     CHECK(isIdentical(compileAndRun<double>(proc), bitAndDouble(a, b)));
2891 }
2892
2893 static float bitAndFloat(float a, float b)
2894 {
2895     return bitwise_cast<float>(bitwise_cast<uint32_t>(a) & bitwise_cast<uint32_t>(b));
2896 }
2897
2898 static void testBitAndArgFloat(float a)
2899 {
2900     Procedure proc;
2901     BasicBlock* root = proc.addBlock();
2902     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2903         root->appendNew<Value>(proc, Trunc, Origin(),
2904             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2905     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2906     root->appendNewControlValue(proc, Return, Origin(), result);
2907
2908     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitAndFloat(a, a)));
2909 }
2910
2911 static void testBitAndArgsFloat(float a, float b)
2912 {
2913     Procedure proc;
2914     BasicBlock* root = proc.addBlock();
2915     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2916         root->appendNew<Value>(proc, Trunc, Origin(),
2917             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2918     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2919         root->appendNew<Value>(proc, Trunc, Origin(),
2920             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2921     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2922     root->appendNewControlValue(proc, Return, Origin(), result);
2923
2924     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2925 }
2926
2927 static void testBitAndArgImmFloat(float a, float b)
2928 {
2929     Procedure proc;
2930     BasicBlock* root = proc.addBlock();
2931     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2932         root->appendNew<Value>(proc, Trunc, Origin(),
2933             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2934     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2935     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2936     root->appendNewControlValue(proc, Return, Origin(), result);
2937
2938     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2939 }
2940
2941 static void testBitAndImmsFloat(float a, float b)
2942 {
2943     Procedure proc;
2944     BasicBlock* root = proc.addBlock();
2945     Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2946     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2947     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2948     root->appendNewControlValue(proc, Return, Origin(), result);
2949
2950     CHECK(isIdentical(compileAndRun<float>(proc), bitAndFloat(a, b)));
2951 }
2952
2953 static void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b)
2954 {
2955     Procedure proc;
2956     BasicBlock* root = proc.addBlock();
2957     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2958         root->appendNew<Value>(proc, Trunc, Origin(),
2959             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2960     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2961         root->appendNew<Value>(proc, Trunc, Origin(),
2962             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2963     Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
2964     Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
2965     Value* doubleResult = root->appendNew<Value>(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble);
2966     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
2967     root->appendNewControlValue(proc, Return, Origin(), floatResult);
2968
2969     double doubleA = a;
2970     double doubleB = b;
2971     float expected = static_cast<float>(bitAndDouble(doubleA, doubleB));
2972     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
2973 }
2974
2975 static void testBitOrArgs(int64_t a, int64_t b)
2976 {
2977     Procedure proc;
2978     BasicBlock* root = proc.addBlock();
2979     root->appendNewControlValue(
2980         proc, Return, Origin(),
2981         root->appendNew<Value>(
2982             proc, BitOr, Origin(),
2983             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2984             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2985
2986     CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b));
2987 }
2988
2989 static void testBitOrSameArg(int64_t a)
2990 {
2991     Procedure proc;
2992     BasicBlock* root = proc.addBlock();
2993     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2994     root->appendNewControlValue(
2995         proc, Return, Origin(),
2996         root->appendNew<Value>(
2997             proc, BitOr, Origin(),
2998             argument,
2999             argument));
3000
3001     CHECK(compileAndRun<int64_t>(proc, a) == a);
3002 }
3003
3004 static void testBitOrAndAndArgs(int64_t a, int64_t b, int64_t c)
3005 {
3006     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3007     // ((a & b) | (a & c))
3008     // ((a & b) | (c & a))
3009     // ((b & a) | (a & c))
3010     // ((b & a) | (c & a))
3011     for (int i = 0; i < 4; ++i) {
3012         Procedure proc;
3013         BasicBlock* root = proc.addBlock();
3014         Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3015         Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3016         Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
3017         Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3018             : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3019         Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
3020             : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
3021         root->appendNewControlValue(
3022             proc, Return, Origin(),
3023             root->appendNew<Value>(
3024                 proc, BitOr, Origin(),
3025                 andAB,
3026                 andAC));
3027
3028         CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a & b) | (a & c)));
3029     }
3030 }
3031
3032 static void testBitOrAndAndArgs32(int32_t a, int32_t b, int32_t c)
3033 {
3034     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3035     // ((a & b) | (a & c))
3036     // ((a & b) | (c & a))
3037     // ((b & a) | (a & c))
3038     // ((b & a) | (c & a))
3039     for (int i = 0; i < 4; ++i) {
3040         Procedure proc;
3041         BasicBlock* root = proc.addBlock();
3042         Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3043         Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3044         Value* argC = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
3045         Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3046             : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3047         Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
3048             : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
3049         root->appendNewControlValue(
3050             proc, Return, Origin(),
3051             root->appendNew<Value>(
3052                 proc, BitOr, Origin(),
3053                 andAB,
3054                 andAC));
3055
3056         CHECK_EQ(compileAndRun<int32_t>(proc, a, b, c), ((a & b) | (a & c)));
3057     }
3058 }
3059
3060 static void testBitOrAndSameArgs(int64_t a, int64_t b)
3061 {
3062     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3063     // ((a & b) | a)
3064     // ((b & a) | a)
3065     // (a | (a & b))
3066     // (a | (b & a))
3067     for (int i = 0; i < 4; ++i) {
3068         Procedure proc;
3069         BasicBlock* root = proc.addBlock();
3070         Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3071         Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3072         Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3073             : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3074         Value* result = i & 2 ? root->appendNew<Value>(proc, BitOr, Origin(), andAB, argA)
3075             : root->appendNew<Value>(proc, BitOr, Origin(), argA, andAB);
3076         root->appendNewControlValue(proc, Return, Origin(), result);
3077
3078         CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a & b) | a));
3079     }
3080 }
3081
3082 static void testBitOrAndSameArgs32(int32_t a, int32_t b)
3083 {
3084     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3085     // ((a & b) | a)
3086     // ((b & a) | a)
3087     // (a | (a & b))
3088     // (a | (b & a))
3089     for (int i = 0; i < 4; ++i) {
3090         Procedure proc;
3091         BasicBlock* root = proc.addBlock();
3092         Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3093         Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3094         Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3095             : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3096         Value* result = i & 2 ? root->appendNew<Value>(proc, BitOr, Origin(), andAB, argA)
3097             : root->appendNew<Value>(proc, BitOr, Origin(), argA, andAB);
3098         root->appendNewControlValue(proc, Return, Origin(), result);
3099
3100         CHECK_EQ(compileAndRun<int32_t>(proc, a, b), ((a & b) | a));
3101     }
3102 }
3103
3104 static void testBitOrNotNot(int64_t a, int64_t b)
3105 {
3106     Procedure proc;
3107     BasicBlock* root = proc.addBlock();
3108     Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3109     Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3110     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
3111     Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const64Value>(proc, Origin(), -1));
3112     root->appendNewControlValue(
3113         proc, Return, Origin(),
3114         root->appendNew<Value>(
3115             proc, BitOr, Origin(),
3116             notA,
3117             notB));
3118
3119     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | ~b));
3120 }
3121
3122 static void testBitOrNotNot32(int32_t a, int32_t b)
3123 {
3124     Procedure proc;
3125     BasicBlock* root = proc.addBlock();
3126     Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3127     Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3128     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
3129     Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const32Value>(proc, Origin(), -1));
3130     root->appendNewControlValue(
3131         proc, Return, Origin(),
3132         root->appendNew<Value>(
3133             proc, BitOr, Origin(),
3134             notA,
3135             notB));
3136
3137     CHECK_EQ(compileAndRun<int32_t>(proc, a, b), (~a | ~b));
3138 }
3139
3140 static void testBitOrNotImm(int64_t a, int64_t b)
3141 {
3142     Procedure proc;
3143     BasicBlock* root = proc.addBlock();
3144     Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3145     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
3146     Value* cstB = root->appendNew<Const64Value>(proc, Origin(), b);
3147     root->appendNewControlValue(
3148         proc, Return, Origin(),
3149         root->appendNew<Value>(
3150             proc, BitOr, Origin(),
3151             notA,
3152             cstB));
3153
3154     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | b));
3155 }
3156
3157 static void testBitOrNotImm32(int32_t a, int32_t b)
3158 {
3159     Procedure proc;
3160     BasicBlock* root = proc.addBlock();
3161     Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3162     Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
3163     Value* cstB = root->appendNew<Const32Value>(proc, Origin(), b);
3164     root->appendNewControlValue(
3165         proc, Return, Origin(),
3166         root->appendNew<Value>(
3167             proc, BitOr, Origin(),
3168             notA,
3169             cstB));
3170
3171     CHECK_EQ(compileAndRun<int32_t>(proc, a), (~a | b));
3172 }
3173
3174 static void testBitOrImms(int64_t a, int64_t b)
3175 {
3176     Procedure proc;
3177     BasicBlock* root = proc.addBlock();
3178     root->appendNewControlValue(
3179         proc, Return, Origin(),
3180         root->appendNew<Value>(
3181             proc, BitOr, Origin(),
3182             root->appendNew<Const64Value>(proc, Origin(), a),
3183             root->appendNew<Const64Value>(proc, Origin(), b)));
3184
3185     CHECK(compileAndRun<int64_t>(proc) == (a | b));
3186 }
3187
3188 static void testBitOrArgImm(int64_t a, int64_t b)
3189 {
3190     Procedure proc;
3191     BasicBlock* root = proc.addBlock();
3192     root->appendNewControlValue(
3193         proc, Return, Origin(),
3194         root->appendNew<Value>(
3195             proc, BitOr, Origin(),
3196             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3197             root->appendNew<Const64Value>(proc, Origin(), b)));
3198
3199     CHECK(compileAndRun<int64_t>(proc, a) == (a | b));
3200 }
3201
3202 static void testBitOrImmArg(int64_t a, int64_t b)
3203 {
3204     Procedure proc;
3205     BasicBlock* root = proc.addBlock();
3206     root->appendNewControlValue(
3207         proc, Return, Origin(),
3208         root->appendNew<Value>(
3209             proc, BitOr, Origin(),
3210             root->appendNew<Const64Value>(proc, Origin(), a),
3211             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3212
3213     CHECK(compileAndRun<int64_t>(proc, b) == (a | b));
3214 }
3215
3216 static void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c)
3217 {
3218     Procedure proc;
3219     BasicBlock* root = proc.addBlock();
3220     Value* innerBitOr = root->appendNew<Value>(
3221         proc, BitOr, Origin(),
3222         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3223         root->appendNew<Const64Value>(proc, Origin(), b));
3224     root->appendNewControlValue(
3225         proc, Return, Origin(),
3226         root->appendNew<Value>(
3227             proc, BitOr, Origin(),
3228             innerBitOr,
3229             root->appendNew<Const64Value>(proc, Origin(), c)));
3230
3231     CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c));
3232 }
3233
3234 static void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c)
3235 {
3236     Procedure proc;
3237     BasicBlock* root = proc.addBlock();
3238     Value* innerBitOr = root->appendNew<Value>(
3239         proc, BitOr, Origin(),
3240         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3241         root->appendNew<Const64Value>(proc, Origin(), c));
3242     root->appendNewControlValue(
3243         proc, Return, Origin(),
3244         root->appendNew<Value>(
3245             proc, BitOr, Origin(),
3246             root->appendNew<Const64Value>(proc, Origin(), a),
3247             innerBitOr));
3248
3249     CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c)));
3250 }
3251
3252 static void testBitOrArgs32(int a, int b)
3253 {
3254     Procedure proc;
3255     BasicBlock* root = proc.addBlock();
3256     root->appendNewControlValue(
3257         proc, Return, Origin(),
3258         root->appendNew<Value>(
3259             proc, BitOr, Origin(),
3260             root->appendNew<Value>(
3261                 proc, Trunc, Origin(),
3262                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3263             root->appendNew<Value>(
3264                 proc, Trunc, Origin(),
3265                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3266
3267     CHECK(compileAndRun<int>(proc, a, b) == (a | b));
3268 }
3269
3270 static void testBitOrSameArg32(int a)
3271 {
3272     Procedure proc;
3273     BasicBlock* root = proc.addBlock();
3274     Value* argument = root->appendNew<Value>(
3275         proc, Trunc, Origin(),
3276             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3277     root->appendNewControlValue(
3278         proc, Return, Origin(),
3279         root->appendNew<Value>(
3280             proc, BitOr, Origin(),
3281             argument,
3282             argument));
3283
3284     CHECK(compileAndRun<int>(proc, a) == a);
3285 }
3286
3287 static void testBitOrImms32(int a, int b)
3288 {
3289     Procedure proc;
3290     BasicBlock* root = proc.addBlock();
3291     root->appendNewControlValue(
3292         proc, Return, Origin(),
3293         root->appendNew<Value>(
3294             proc, BitOr, Origin(),
3295             root->appendNew<Const32Value>(proc, Origin(), a),
3296             root->appendNew<Const32Value>(proc, Origin(), b)));
3297
3298     CHECK(compileAndRun<int>(proc) == (a | b));
3299 }
3300
3301 static void testBitOrArgImm32(int a, int b)
3302 {
3303     Procedure proc;
3304     BasicBlock* root = proc.addBlock();
3305     root->appendNewControlValue(
3306         proc, Return, Origin(),
3307         root->appendNew<Value>(
3308             proc, BitOr, Origin(),
3309             root->appendNew<Value>(
3310                 proc, Trunc, Origin(),
3311                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3312             root->appendNew<Const32Value>(proc, Origin(), b)));
3313
3314     CHECK(compileAndRun<int>(proc, a) == (a | b));
3315 }
3316
3317 static void testBitOrImmArg32(int a, int b)
3318 {
3319     Procedure proc;
3320     BasicBlock* root = proc.addBlock();
3321     root->appendNewControlValue(
3322         proc, Return, Origin(),
3323         root->appendNew<Value>(
3324             proc, BitOr, Origin(),
3325             root->appendNew<Const32Value>(proc, Origin(), a),
3326             root->appendNew<Value>(
3327                 proc, Trunc, Origin(),
3328                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3329
3330     CHECK(compileAndRun<int>(proc, b) == (a | b));
3331 }
3332
3333 void addBitTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks)
3334 {
3335     RUN(testBitAndArgs(43, 43));
3336     RUN(testBitAndArgs(43, 0));
3337     RUN(testBitAndArgs(10, 3));
3338     RUN(testBitAndArgs(42, 0xffffffffffffffff));
3339     RUN(testBitAndSameArg(43));
3340     RUN(testBitAndSameArg(0));
3341     RUN(testBitAndSameArg(3));
3342     RUN(testBitAndSameArg(0xffffffffffffffff));
3343     RUN(testBitAndImms(43, 43));
3344     RUN(testBitAndImms(43, 0));
3345     RUN(testBitAndImms(10, 3));
3346     RUN(testBitAndImms(42, 0xffffffffffffffff));
3347     RUN(testBitAndArgImm(43, 43));
3348     RUN(testBitAndArgImm(43, 0));
3349     RUN(testBitAndArgImm(10, 3));
3350     RUN(testBitAndArgImm(42, 0xffffffffffffffff));
3351     RUN(testBitAndArgImm(42, 0xff));
3352     RUN(testBitAndArgImm(300, 0xff));
3353     RUN(testBitAndArgImm(-300, 0xff));
3354     RUN(testBitAndArgImm(42, 0xffff));
3355     RUN(testBitAndArgImm(40000, 0xffff));
3356     RUN(testBitAndArgImm(-40000, 0xffff));
3357     RUN(testBitAndImmArg(43, 43));
3358     RUN(testBitAndImmArg(43, 0));
3359     RUN(testBitAndImmArg(10, 3));
3360     RUN(testBitAndImmArg(42, 0xffffffffffffffff));
3361     RUN(testBitAndBitAndArgImmImm(2, 7, 3));
3362     RUN(testBitAndBitAndArgImmImm(1, 6, 6));
3363     RUN(testBitAndBitAndArgImmImm(0xffff, 24, 7));
3364     RUN(testBitAndImmBitAndArgImm(7, 2, 3));
3365     RUN(testBitAndImmBitAndArgImm(6, 1, 6));
3366     RUN(testBitAndImmBitAndArgImm(24, 0xffff, 7));
3367     RUN(testBitAndArgs32(43, 43));
3368     RUN(testBitAndArgs32(43, 0));
3369     RUN(testBitAndArgs32(10, 3));
3370     RUN(testBitAndArgs32(42, 0xffffffff));
3371     RUN(testBitAndSameArg32(43));
3372     RUN(testBitAndSameArg32(0));
3373     RUN(testBitAndSameArg32(3));
3374     RUN(testBitAndSameArg32(0xffffffff));
3375     RUN(testBitAndImms32(43, 43));
3376     RUN(testBitAndImms32(43, 0));
3377     RUN(testBitAndImms32(10, 3));
3378     RUN(testBitAndImms32(42, 0xffffffff));
3379     RUN(testBitAndArgImm32(43, 43));
3380     RUN(testBitAndArgImm32(43, 0));
3381     RUN(testBitAndArgImm32(10, 3));
3382     RUN(testBitAndArgImm32(42, 0xffffffff));
3383     RUN(testBitAndImmArg32(43, 43));
3384     RUN(testBitAndImmArg32(43, 0));
3385     RUN(testBitAndImmArg32(10, 3));
3386     RUN(testBitAndImmArg32(42, 0xffffffff));
3387     RUN(testBitAndImmArg32(42, 0xff));
3388     RUN(testBitAndImmArg32(300, 0xff));
3389     RUN(testBitAndImmArg32(-300, 0xff));
3390     RUN(testBitAndImmArg32(42, 0xffff));
3391     RUN(testBitAndImmArg32(40000, 0xffff));
3392     RUN(testBitAndImmArg32(-40000, 0xffff));
3393     RUN(testBitAndBitAndArgImmImm32(2, 7, 3));
3394     RUN(testBitAndBitAndArgImmImm32(1, 6, 6));
3395     RUN(testBitAndBitAndArgImmImm32(0xffff, 24, 7));
3396     RUN(testBitAndImmBitAndArgImm32(7, 2, 3));
3397     RUN(testBitAndImmBitAndArgImm32(6, 1, 6));
3398     RUN(testBitAndImmBitAndArgImm32(24, 0xffff, 7));
3399     RUN_BINARY(testBitAndWithMaskReturnsBooleans, int64Operands(), int64Operands());
3400     RUN_UNARY(testBitAndArgDouble, floatingPointOperands<double>());
3401     RUN_BINARY(testBitAndArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3402     RUN_BINARY(testBitAndArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3403     RUN_BINARY(testBitAndImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3404     RUN_UNARY(testBitAndArgFloat, floatingPointOperands<float>());
3405     RUN_BINARY(testBitAndArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3406     RUN_BINARY(testBitAndArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3407     RUN_BINARY(testBitAndImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3408     RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3409     RUN_BINARY(testBitAndNotNot, int64Operands(), int64Operands());
3410     RUN_BINARY(testBitAndNotNot32, int32Operands(), int32Operands());
3411     RUN_BINARY(testBitAndNotImm, int64Operands(), int64Operands());
3412     RUN_BINARY(testBitAndNotImm32, int32Operands(), int32Operands());
3413     
3414     RUN(testBitOrArgs(43, 43));
3415     RUN(testBitOrArgs(43, 0));
3416     RUN(testBitOrArgs(10, 3));
3417     RUN(testBitOrArgs(42, 0xffffffffffffffff));
3418     RUN(testBitOrSameArg(43));
3419     RUN(testBitOrSameArg(0));
3420     RUN(testBitOrSameArg(3));
3421     RUN(testBitOrSameArg(0xffffffffffffffff));
3422     RUN(testBitOrImms(43, 43));
3423     RUN(testBitOrImms(43, 0));
3424     RUN(testBitOrImms(10, 3));
3425     RUN(testBitOrImms(42, 0xffffffffffffffff));
3426     RUN(testBitOrArgImm(43, 43));
3427     RUN(testBitOrArgImm(43, 0));
3428     RUN(testBitOrArgImm(10, 3));
3429     RUN(testBitOrArgImm(42, 0xffffffffffffffff));
3430     RUN(testBitOrImmArg(43, 43));
3431     RUN(testBitOrImmArg(43, 0));
3432     RUN(testBitOrImmArg(10, 3));
3433     RUN(testBitOrImmArg(42, 0xffffffffffffffff));
3434     RUN(testBitOrBitOrArgImmImm(2, 7, 3));
3435     RUN(testBitOrBitOrArgImmImm(1, 6, 6));
3436     RUN(testBitOrBitOrArgImmImm(0xffff, 24, 7));
3437     RUN(testBitOrImmBitOrArgImm(7, 2, 3));
3438     RUN(testBitOrImmBitOrArgImm(6, 1, 6));
3439     RUN(testBitOrImmBitOrArgImm(24, 0xffff, 7));
3440     RUN(testBitOrArgs32(43, 43));
3441     RUN(testBitOrArgs32(43, 0));
3442     RUN(testBitOrArgs32(10, 3));
3443     RUN(testBitOrArgs32(42, 0xffffffff));
3444     RUN(testBitOrSameArg32(43));
3445     RUN(testBitOrSameArg32(0));
3446     RUN(testBitOrSameArg32(3));
3447     RUN(testBitOrSameArg32(0xffffffff));
3448     RUN(testBitOrImms32(43, 43));
3449     RUN(testBitOrImms32(43, 0));
3450     RUN(testBitOrImms32(10, 3));
3451     RUN(testBitOrImms32(42, 0xffffffff));
3452     RUN(testBitOrArgImm32(43, 43));
3453     RUN(testBitOrArgImm32(43, 0));
3454     RUN(testBitOrArgImm32(10, 3));
3455     RUN(testBitOrArgImm32(42, 0xffffffff));
3456     RUN(testBitOrImmArg32(43, 43));
3457     RUN(testBitOrImmArg32(43, 0));
3458     RUN(testBitOrImmArg32(10, 3));
3459     RUN(testBitOrImmArg32(42, 0xffffffff));
3460     RUN(testBitOrBitOrArgImmImm32(2, 7, 3));
3461     RUN(testBitOrBitOrArgImmImm32(1, 6, 6));
3462     RUN(testBitOrBitOrArgImmImm32(0xffff, 24, 7));
3463     RUN(testBitOrImmBitOrArgImm32(7, 2, 3));
3464     RUN(testBitOrImmBitOrArgImm32(6, 1, 6));
3465     RUN(testBitOrImmBitOrArgImm32(24, 0xffff, 7));
3466     RUN_UNARY(testBitOrArgDouble, floatingPointOperands<double>());
3467     RUN_BINARY(testBitOrArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3468     RUN_BINARY(testBitOrArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3469     RUN_BINARY(testBitOrImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
3470     RUN_UNARY(testBitOrArgFloat, floatingPointOperands<float>());
3471     RUN_BINARY(testBitOrArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3472     RUN_BINARY(testBitOrArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3473     RUN_BINARY(testBitOrImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
3474     RUN_BINARY(testBitOrArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
3475     RUN_TERNARY(testBitOrAndAndArgs, int64Operands(), int64Operands(), int64Operands());
3476     RUN_TERNARY(testBitOrAndAndArgs32, int32Operands(), int32Operands(), int32Operands());
3477     RUN_BINARY(testBitOrAndSameArgs, int64Operands(), int64Operands());
3478     RUN_BINARY(testBitOrAndSameArgs32, int32Operands(), int32Operands());
3479     RUN_BINARY(testBitOrNotNot, int64Operands(), int64Operands());
3480     RUN_BINARY(testBitOrNotNot32, int32Operands(), int32Operands());
3481     RUN_BINARY(testBitOrNotImm, int64Operands(), int64Operands());
3482     RUN_BINARY(testBitOrNotImm32, int32Operands(), int32Operands());
3483     
3484     RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands());
3485     RUN_UNARY(testBitXorSameArg, int64Operands());
3486     RUN_BINARY(testBitXorImms, int64Operands(), int64Operands());
3487     RUN_BINARY(testBitXorArgImm, int64Operands(), int64Operands());
3488     RUN_BINARY(testBitXorImmArg, int64Operands(), int64Operands());
3489     RUN(testBitXorBitXorArgImmImm(2, 7, 3));
3490     RUN(testBitXorBitXorArgImmImm(1, 6, 6));
3491     RUN(testBitXorBitXorArgImmImm(0xffff, 24, 7));
3492     RUN(testBitXorImmBitXorArgImm(7, 2, 3));
3493     RUN(testBitXorImmBitXorArgImm(6, 1, 6));
3494     RUN(testBitXorImmBitXorArgImm(24, 0xffff, 7));
3495     RUN(testBitXorArgs32(43, 43));
3496     RUN(testBitXorArgs32(43, 0));
3497     RUN(testBitXorArgs32(10, 3));
3498     RUN(testBitXorArgs32(42, 0xffffffff));
3499     RUN(testBitXorSameArg32(43));
3500     RUN(testBitXorSameArg32(0));
3501     RUN(testBitXorSameArg32(3));
3502     RUN(testBitXorSameArg32(0xffffffff));
3503     RUN(testBitXorImms32(43, 43));
3504     RUN(testBitXorImms32(43, 0));
3505     RUN(testBitXorImms32(10, 3));
3506     RUN(testBitXorImms32(42, 0xffffffff));
3507     RUN(testBitXorArgImm32(43, 43));
3508     RUN(testBitXorArgImm32(43, 0));
3509     RUN(testBitXorArgImm32(10, 3));
3510     RUN(testBitXorArgImm32(42, 0xffffffff));
3511     RUN(testBitXorImmArg32(43, 43));
3512     RUN(testBitXorImmArg32(43, 0));
3513     RUN(testBitXorImmArg32(10, 3));
3514     RUN(testBitXorImmArg32(42, 0xffffffff));
3515     RUN(testBitXorBitXorArgImmImm32(2, 7, 3));
3516     RUN(testBitXorBitXorArgImmImm32(1, 6, 6));
3517     RUN(testBitXorBitXorArgImmImm32(0xffff, 24, 7));
3518     RUN(testBitXorImmBitXorArgImm32(7, 2, 3));
3519     RUN(testBitXorImmBitXorArgImm32(6, 1, 6));
3520     RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7));
3521     RUN_TERNARY(testBitXorAndAndArgs, int64Operands(), int64Operands(), int64Operands());
3522     RUN_TERNARY(testBitXorAndAndArgs32, int32Operands(), int32Operands(), int32Operands());
3523     RUN_BINARY(testBitXorAndSameArgs, int64Operands(), int64Operands());
3524     RUN_BINARY(testBitXorAndSameArgs32, int32Operands(), int32Operands());
3525     
3526     RUN_UNARY(testBitNotArg, int64Operands());
3527     RUN_UNARY(testBitNotImm, int64Operands());
3528     RUN_UNARY(testBitNotMem, int64Operands());
3529     RUN_UNARY(testBitNotArg32, int32Operands());
3530     RUN_UNARY(testBitNotImm32, int32Operands());
3531     RUN_UNARY(testBitNotMem32, int32Operands());
3532     RUN_BINARY(testNotOnBooleanAndBranch32, int32Operands(), int32Operands());
3533     RUN_BINARY(testBitNotOnBooleanAndBranch32, int32Operands(), int32Operands());
3534     
3535     RUN_BINARY(testBitXorTreeArgs, int64Operands(), int64Operands());
3536     RUN_BINARY(testBitXorTreeArgsEven, int64Operands(), int64Operands());
3537     RUN_BINARY(testBitXorTreeArgImm, int64Operands(), int64Operands());
3538     RUN_UNARY(testBitAndTreeArg32, int32Operands());
3539     RUN_UNARY(testBitOrTreeArg32, int32Operands());
3540 }
3541
3542 #endif // ENABLE(B3_JIT)