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