562ac86bd8f1d4ea56f012e2a6e0bd3176dd006b
[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 testAddFPRArgsFloat(float a, float b)
718 {
719     Procedure proc;
720     BasicBlock* root = proc.addBlock();
721     Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
722         root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
723     Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
724         root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
725     Value* result = root->appendNew<Value>(proc, Add, Origin(), argument1, argument2);
726     root->appendNewControlValue(proc, Return, Origin(), result);
727
728     CHECK(isIdentical(compileAndRun<float>(proc, a, b), a + b));
729 }
730
731 void testAddArgImmFloat(float a, float b)
732 {
733     Procedure proc;
734     BasicBlock* root = proc.addBlock();
735     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
736         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
737     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
738     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
739     Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue, constValue);
740     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
741     root->appendNewControlValue(proc, Return, Origin(), result32);
742
743     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + b)));
744 }
745
746 void testAddImmArgFloat(float a, float b)
747 {
748     Procedure proc;
749     BasicBlock* root = proc.addBlock();
750     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
751         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
752     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
753     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
754     Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue, floatValue);
755     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
756     root->appendNewControlValue(proc, Return, Origin(), result32);
757
758     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
759 }
760
761 void testAddImmsFloat(float a, float b)
762 {
763     Procedure proc;
764     BasicBlock* root = proc.addBlock();
765     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
766     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
767     Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue1, constValue2);
768     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
769     root->appendNewControlValue(proc, Return, Origin(), result32);
770
771     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a + b)));
772 }
773
774 void testAddArgFloatWithUselessDoubleConversion(float a)
775 {
776     Procedure proc;
777     BasicBlock* root = proc.addBlock();
778     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
779         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
780     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
781     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
782     Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble, asDouble);
783     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
784     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
785     root->appendNewControlValue(proc, Return, Origin(), result32);
786
787     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + a)));
788 }
789
790 void testAddArgsFloatWithUselessDoubleConversion(float a, float b)
791 {
792     Procedure proc;
793     BasicBlock* root = proc.addBlock();
794     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
795         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
796     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
797         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
798     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
799     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
800     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
801     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
802     Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2);
803     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
804     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
805     root->appendNewControlValue(proc, Return, Origin(), result32);
806
807     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
808 }
809
810 void testAddArgsFloatWithEffectfulDoubleConversion(float a, float b)
811 {
812     Procedure proc;
813     BasicBlock* root = proc.addBlock();
814     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
815         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
816     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
817         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
818     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
819     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
820     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
821     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
822     Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2);
823     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
824     Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
825     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
826     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
827     root->appendNewControlValue(proc, Return, Origin(), result32);
828
829     double effect = 0;
830     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a + b)));
831     CHECK(isIdentical(effect, static_cast<double>(a) + static_cast<double>(b)));
832 }
833
834 void testMulArg(int a)
835 {
836     Procedure proc;
837     BasicBlock* root = proc.addBlock();
838     Value* value = root->appendNew<Value>(
839         proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
840     root->appendNewControlValue(
841         proc, Return, Origin(),
842         root->appendNew<Value>(proc, Mul, Origin(), value, value));
843
844     CHECK(compileAndRun<int>(proc, a) == a * a);
845 }
846
847 void testMulArgStore(int a)
848 {
849     Procedure proc;
850     BasicBlock* root = proc.addBlock();
851
852     int mulSlot;
853     int valueSlot;
854     
855     Value* value = root->appendNew<Value>(
856         proc, Trunc, Origin(),
857         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
858     Value* mul = root->appendNew<Value>(proc, Mul, Origin(), value, value);
859
860     root->appendNew<MemoryValue>(
861         proc, Store, Origin(), value,
862         root->appendNew<ConstPtrValue>(proc, Origin(), &valueSlot));
863     root->appendNew<MemoryValue>(
864         proc, Store, Origin(), mul,
865         root->appendNew<ConstPtrValue>(proc, Origin(), &mulSlot));
866
867     root->appendNewControlValue(
868         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
869
870     CHECK(!compileAndRun<int>(proc, a));
871     CHECK(mulSlot == a * a);
872     CHECK(valueSlot == a);
873 }
874
875 void testMulAddArg(int a)
876 {
877     Procedure proc;
878     BasicBlock* root = proc.addBlock();
879     Value* value = root->appendNew<Value>(
880         proc, Trunc, Origin(),
881         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
882     root->appendNewControlValue(
883         proc, Return, Origin(),
884         root->appendNew<Value>(
885             proc, Add, Origin(),
886             root->appendNew<Value>(proc, Mul, Origin(), value, value),
887             value));
888
889     CHECK(compileAndRun<int>(proc, a) == a * a + a);
890 }
891
892 void testMulArgs(int a, int 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<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
902
903     CHECK(compileAndRun<int>(proc, a, b) == a * b);
904 }
905
906 void testMulArgImm(int64_t a, int64_t 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<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
915             root->appendNew<Const64Value>(proc, Origin(), b)));
916
917     CHECK(compileAndRun<int64_t>(proc, a) == a * b);
918 }
919
920 void testMulImmArg(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<Const64Value>(proc, Origin(), a),
929             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
930
931     CHECK(compileAndRun<int>(proc, b) == a * b);
932 }
933
934 void testMulArgs32(int a, int b)
935 {
936     Procedure proc;
937     BasicBlock* root = proc.addBlock();
938     root->appendNewControlValue(
939         proc, Return, Origin(),
940         root->appendNew<Value>(
941             proc, Mul, Origin(),
942             root->appendNew<Value>(
943                 proc, Trunc, Origin(),
944                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
945             root->appendNew<Value>(
946                 proc, Trunc, Origin(),
947                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
948
949     CHECK(compileAndRun<int>(proc, a, b) == a * b);
950 }
951
952 void testMulLoadTwice()
953 {
954     auto test = [&] (unsigned optLevel) {
955         Procedure proc;
956         BasicBlock* root = proc.addBlock();
957         int32_t value = 42;
958         Value* load = root->appendNew<MemoryValue>(
959             proc, Load, Int32, Origin(),
960             root->appendNew<ConstPtrValue>(proc, Origin(), &value));
961         root->appendNewControlValue(
962             proc, Return, Origin(),
963             root->appendNew<Value>(proc, Mul, Origin(), load, load));
964
965         auto code = compile(proc, optLevel);
966         CHECK(invoke<int32_t>(*code) == 42 * 42);
967     };
968
969     test(0);
970     test(1);
971 }
972
973 void testMulAddArgsLeft()
974 {
975     Procedure proc;
976     BasicBlock* root = proc.addBlock();
977
978     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
979     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
980     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
981     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
982     Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2);
983     root->appendNewControlValue(proc, Return, Origin(), added);
984
985     auto code = compile(proc);
986
987     auto testValues = int64Operands();
988     for (auto a : testValues) {
989         for (auto b : testValues) {
990             for (auto c : testValues) {
991                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
992             }
993         }
994     }
995 }
996
997 void testMulAddArgsRight()
998 {
999     Procedure proc;
1000     BasicBlock* root = proc.addBlock();
1001
1002     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1003     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1004     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1005     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1006     Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied);
1007     root->appendNewControlValue(proc, Return, Origin(), added);
1008
1009     auto code = compile(proc);
1010
1011     auto testValues = int64Operands();
1012     for (auto a : testValues) {
1013         for (auto b : testValues) {
1014             for (auto c : testValues) {
1015                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
1016             }
1017         }
1018     }
1019 }
1020
1021 void testMulAddArgsLeft32()
1022 {
1023     Procedure proc;
1024     BasicBlock* root = proc.addBlock();
1025
1026     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1027         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1028     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1029         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1030     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1031         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1032     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1033     Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2);
1034     root->appendNewControlValue(proc, Return, Origin(), added);
1035
1036     auto code = compile(proc);
1037
1038     auto testValues = int32Operands();
1039     for (auto a : testValues) {
1040         for (auto b : testValues) {
1041             for (auto c : testValues) {
1042                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
1043             }
1044         }
1045     }
1046 }
1047
1048 void testMulAddArgsRight32()
1049 {
1050     Procedure proc;
1051     BasicBlock* root = proc.addBlock();
1052
1053     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1054         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1055     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1056         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1057     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1058         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1059     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1060     Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied);
1061     root->appendNewControlValue(proc, Return, Origin(), added);
1062
1063     auto code = compile(proc);
1064
1065     auto testValues = int32Operands();
1066     for (auto a : testValues) {
1067         for (auto b : testValues) {
1068             for (auto c : testValues) {
1069                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
1070             }
1071         }
1072     }
1073 }
1074
1075 void testMulSubArgsLeft()
1076 {
1077     Procedure proc;
1078     BasicBlock* root = proc.addBlock();
1079
1080     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1081     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1082     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1083     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1084     Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
1085     root->appendNewControlValue(proc, Return, Origin(), added);
1086
1087     auto code = compile(proc);
1088
1089     auto testValues = int64Operands();
1090     for (auto a : testValues) {
1091         for (auto b : testValues) {
1092             for (auto c : testValues) {
1093                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
1094             }
1095         }
1096     }
1097 }
1098
1099 void testMulSubArgsRight()
1100 {
1101     Procedure proc;
1102     BasicBlock* root = proc.addBlock();
1103
1104     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1105     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1106     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1107     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1108     Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
1109     root->appendNewControlValue(proc, Return, Origin(), added);
1110
1111     auto code = compile(proc);
1112
1113     auto testValues = int64Operands();
1114     for (auto a : testValues) {
1115         for (auto b : testValues) {
1116             for (auto c : testValues) {
1117                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
1118             }
1119         }
1120     }
1121 }
1122
1123 void testMulSubArgsLeft32()
1124 {
1125     Procedure proc;
1126     BasicBlock* root = proc.addBlock();
1127
1128     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1129         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1130     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1131         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1132     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1133         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1134     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1135     Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
1136     root->appendNewControlValue(proc, Return, Origin(), added);
1137
1138     auto code = compile(proc);
1139
1140     auto testValues = int32Operands();
1141     for (auto a : testValues) {
1142         for (auto b : testValues) {
1143             for (auto c : testValues) {
1144                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
1145             }
1146         }
1147     }
1148 }
1149
1150 void testMulSubArgsRight32()
1151 {
1152     Procedure proc;
1153     BasicBlock* root = proc.addBlock();
1154
1155     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1156         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1157     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1158         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1159     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1160         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1161     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1162     Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
1163     root->appendNewControlValue(proc, Return, Origin(), added);
1164
1165     auto code = compile(proc);
1166
1167     auto testValues = int32Operands();
1168     for (auto a : testValues) {
1169         for (auto b : testValues) {
1170             for (auto c : testValues) {
1171                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
1172             }
1173         }
1174     }
1175 }
1176
1177 void testMulNegArgs()
1178 {
1179     Procedure proc;
1180     BasicBlock* root = proc.addBlock();
1181
1182     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1183     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1184     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1185     Value* zero = root->appendNew<Const64Value>(proc, Origin(), 0);
1186     Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
1187     root->appendNewControlValue(proc, Return, Origin(), added);
1188
1189     auto code = compile(proc);
1190
1191     auto testValues = int64Operands();
1192     for (auto a : testValues) {
1193         for (auto b : testValues) {
1194             CHECK(invoke<int64_t>(*code, a.value, b.value) == -(a.value * b.value));
1195         }
1196     }
1197 }
1198
1199 void testMulNegArgs32()
1200 {
1201     Procedure proc;
1202     BasicBlock* root = proc.addBlock();
1203
1204     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1205         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1206     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1207         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1208     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1209     Value* zero = root->appendNew<Const32Value>(proc, Origin(), 0);
1210     Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
1211     root->appendNewControlValue(proc, Return, Origin(), added);
1212
1213     auto code = compile(proc);
1214
1215     auto testValues = int32Operands();
1216     for (auto a : testValues) {
1217         for (auto b : testValues) {
1218             CHECK(invoke<int32_t>(*code, a.value, b.value) == -(a.value * b.value));
1219         }
1220     }
1221 }
1222
1223 void testMulArgDouble(double a)
1224 {
1225     Procedure proc;
1226     BasicBlock* root = proc.addBlock();
1227     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1228     root->appendNewControlValue(
1229         proc, Return, Origin(),
1230         root->appendNew<Value>(proc, Mul, Origin(), value, value));
1231
1232     CHECK(isIdentical(compileAndRun<double>(proc, a), a * a));
1233 }
1234
1235 void testMulArgsDouble(double a, double b)
1236 {
1237     Procedure proc;
1238     BasicBlock* root = proc.addBlock();
1239     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1240     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1241     root->appendNewControlValue(
1242         proc, Return, Origin(),
1243         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1244
1245     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a * b));
1246 }
1247
1248 void testMulArgImmDouble(double a, double b)
1249 {
1250     Procedure proc;
1251     BasicBlock* root = proc.addBlock();
1252     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1253     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1254     root->appendNewControlValue(
1255         proc, Return, Origin(),
1256         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1257
1258     CHECK(isIdentical(compileAndRun<double>(proc, a), a * b));
1259 }
1260
1261 void testMulImmArgDouble(double a, double b)
1262 {
1263     Procedure proc;
1264     BasicBlock* root = proc.addBlock();
1265     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1266     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1267     root->appendNewControlValue(
1268         proc, Return, Origin(),
1269         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1270
1271     CHECK(isIdentical(compileAndRun<double>(proc, b), a * b));
1272 }
1273
1274 void testMulImmsDouble(double a, double b)
1275 {
1276     Procedure proc;
1277     BasicBlock* root = proc.addBlock();
1278     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1279     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1280     root->appendNewControlValue(
1281         proc, Return, Origin(),
1282         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1283
1284     CHECK(isIdentical(compileAndRun<double>(proc), a * b));
1285 }
1286
1287 void testMulArgFloat(float a)
1288 {
1289     Procedure proc;
1290     BasicBlock* root = proc.addBlock();
1291     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1292         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1293     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1294     Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, floatValue);
1295     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1296     root->appendNewControlValue(proc, Return, Origin(), result32);
1297
1298
1299     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a)));
1300 }
1301
1302 void testMulArgsFloat(float a, float b)
1303 {
1304     Procedure proc;
1305     BasicBlock* root = proc.addBlock();
1306     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1307         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1308     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1309         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1310     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1311     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1312     Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue1, floatValue2);
1313     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1314     root->appendNewControlValue(proc, Return, Origin(), result32);
1315
1316     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1317 }
1318
1319 void testMulArgImmFloat(float a, float b)
1320 {
1321     Procedure proc;
1322     BasicBlock* root = proc.addBlock();
1323     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1324         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1325     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1326     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1327     Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, constValue);
1328     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1329     root->appendNewControlValue(proc, Return, Origin(), result32);
1330
1331     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * b)));
1332 }
1333
1334 void testMulImmArgFloat(float a, float b)
1335 {
1336     Procedure proc;
1337     BasicBlock* root = proc.addBlock();
1338     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1339         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1340     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1341     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1342     Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue, floatValue);
1343     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1344     root->appendNewControlValue(proc, Return, Origin(), result32);
1345
1346     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1347 }
1348
1349 void testMulImmsFloat(float a, float b)
1350 {
1351     Procedure proc;
1352     BasicBlock* root = proc.addBlock();
1353     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1354     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1355     Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue1, constValue2);
1356     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1357     root->appendNewControlValue(proc, Return, Origin(), result32);
1358
1359     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a * b)));
1360 }
1361
1362 void testMulArgFloatWithUselessDoubleConversion(float a)
1363 {
1364     Procedure proc;
1365     BasicBlock* root = proc.addBlock();
1366     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1367         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1368     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1369     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1370     Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble, asDouble);
1371     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1372     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1373     root->appendNewControlValue(proc, Return, Origin(), result32);
1374
1375     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a)));
1376 }
1377
1378 void testMulArgsFloatWithUselessDoubleConversion(float a, float b)
1379 {
1380     Procedure proc;
1381     BasicBlock* root = proc.addBlock();
1382     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1383         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1384     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1385         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1386     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1387     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1388     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1389     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1390     Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2);
1391     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1392     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1393     root->appendNewControlValue(proc, Return, Origin(), result32);
1394
1395     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1396 }
1397
1398 void testMulArgsFloatWithEffectfulDoubleConversion(float a, float b)
1399 {
1400     Procedure proc;
1401     BasicBlock* root = proc.addBlock();
1402     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1403         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1404     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1405         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1406     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1407     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1408     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1409     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1410     Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2);
1411     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1412     Value* doubleMulress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1413     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleMulress);
1414     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1415     root->appendNewControlValue(proc, Return, Origin(), result32);
1416
1417     double effect = 0;
1418     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a * b)));
1419     CHECK(isIdentical(effect, static_cast<double>(a) * static_cast<double>(b)));
1420 }
1421
1422 void testDivArgDouble(double a)
1423 {
1424     Procedure proc;
1425     BasicBlock* root = proc.addBlock();
1426     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1427     root->appendNewControlValue(
1428         proc, Return, Origin(),
1429         root->appendNew<Value>(proc, Div, Origin(), value, value));
1430
1431     CHECK(isIdentical(compileAndRun<double>(proc, a), a / a));
1432 }
1433
1434 void testDivArgsDouble(double a, double b)
1435 {
1436     Procedure proc;
1437     BasicBlock* root = proc.addBlock();
1438     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1439     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1440     root->appendNewControlValue(
1441         proc, Return, Origin(),
1442         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1443
1444     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a / b));
1445 }
1446
1447 void testDivArgImmDouble(double a, double b)
1448 {
1449     Procedure proc;
1450     BasicBlock* root = proc.addBlock();
1451     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1452     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1453     root->appendNewControlValue(
1454         proc, Return, Origin(),
1455         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1456
1457     CHECK(isIdentical(compileAndRun<double>(proc, a), a / b));
1458 }
1459
1460 void testDivImmArgDouble(double a, double b)
1461 {
1462     Procedure proc;
1463     BasicBlock* root = proc.addBlock();
1464     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1465     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1466     root->appendNewControlValue(
1467         proc, Return, Origin(),
1468         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1469
1470     CHECK(isIdentical(compileAndRun<double>(proc, b), a / b));
1471 }
1472
1473 void testDivImmsDouble(double a, double b)
1474 {
1475     Procedure proc;
1476     BasicBlock* root = proc.addBlock();
1477     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1478     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1479     root->appendNewControlValue(
1480         proc, Return, Origin(),
1481         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1482
1483     CHECK(isIdentical(compileAndRun<double>(proc), a / b));
1484 }
1485
1486 void testDivArgFloat(float a)
1487 {
1488     Procedure proc;
1489     BasicBlock* root = proc.addBlock();
1490     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1491         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1492     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1493     Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, floatValue);
1494     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1495     root->appendNewControlValue(proc, Return, Origin(), result32);
1496
1497
1498     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a)));
1499 }
1500
1501 void testDivArgsFloat(float a, float b)
1502 {
1503     Procedure proc;
1504     BasicBlock* root = proc.addBlock();
1505     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1506         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1507     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1508         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1509     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1510     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1511     Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue1, floatValue2);
1512     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1513     root->appendNewControlValue(proc, Return, Origin(), result32);
1514
1515     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1516 }
1517
1518 void testDivArgImmFloat(float a, float b)
1519 {
1520     Procedure proc;
1521     BasicBlock* root = proc.addBlock();
1522     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1523         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1524     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1525     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1526     Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, constValue);
1527     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1528     root->appendNewControlValue(proc, Return, Origin(), result32);
1529
1530     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / b)));
1531 }
1532
1533 void testDivImmArgFloat(float a, float b)
1534 {
1535     Procedure proc;
1536     BasicBlock* root = proc.addBlock();
1537     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1538         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1539     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1540     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1541     Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue, floatValue);
1542     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1543     root->appendNewControlValue(proc, Return, Origin(), result32);
1544
1545     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1546 }
1547
1548 void testDivImmsFloat(float a, float b)
1549 {
1550     Procedure proc;
1551     BasicBlock* root = proc.addBlock();
1552     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1553     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1554     Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue1, constValue2);
1555     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1556     root->appendNewControlValue(proc, Return, Origin(), result32);
1557
1558     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a / b)));
1559 }
1560
1561 void testModArgDouble(double a)
1562 {
1563     Procedure proc;
1564     BasicBlock* root = proc.addBlock();
1565     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1566     root->appendNewControlValue(
1567         proc, Return, Origin(),
1568         root->appendNew<Value>(proc, Mod, Origin(), value, value));
1569
1570     CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, a)));
1571 }
1572
1573 void testModArgsDouble(double a, double b)
1574 {
1575     Procedure proc;
1576     BasicBlock* root = proc.addBlock();
1577     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1578     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1579     root->appendNewControlValue(
1580         proc, Return, Origin(),
1581         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1582
1583     CHECK(isIdentical(compileAndRun<double>(proc, a, b), fmod(a, b)));
1584 }
1585
1586 void testModArgImmDouble(double a, double b)
1587 {
1588     Procedure proc;
1589     BasicBlock* root = proc.addBlock();
1590     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1591     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1592     root->appendNewControlValue(
1593         proc, Return, Origin(),
1594         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1595
1596     CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, b)));
1597 }
1598
1599 void testModImmArgDouble(double a, double b)
1600 {
1601     Procedure proc;
1602     BasicBlock* root = proc.addBlock();
1603     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1604     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1605     root->appendNewControlValue(
1606         proc, Return, Origin(),
1607         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1608
1609     CHECK(isIdentical(compileAndRun<double>(proc, b), fmod(a, b)));
1610 }
1611
1612 void testModImmsDouble(double a, double b)
1613 {
1614     Procedure proc;
1615     BasicBlock* root = proc.addBlock();
1616     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1617     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1618     root->appendNewControlValue(
1619         proc, Return, Origin(),
1620         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1621
1622     CHECK(isIdentical(compileAndRun<double>(proc), fmod(a, b)));
1623 }
1624
1625 void testModArgFloat(float a)
1626 {
1627     Procedure proc;
1628     BasicBlock* root = proc.addBlock();
1629     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1630         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1631     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1632     Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, floatValue);
1633     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1634     root->appendNewControlValue(proc, Return, Origin(), result32);
1635
1636
1637     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, a)))));
1638 }
1639
1640 void testModArgsFloat(float a, float b)
1641 {
1642     Procedure proc;
1643     BasicBlock* root = proc.addBlock();
1644     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1645         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1646     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1647         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1648     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1649     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1650     Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue1, floatValue2);
1651     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1652     root->appendNewControlValue(proc, Return, Origin(), result32);
1653
1654     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)))));
1655 }
1656
1657 void testModArgImmFloat(float a, float b)
1658 {
1659     Procedure proc;
1660     BasicBlock* root = proc.addBlock();
1661     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1662         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1663     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1664     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1665     Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, constValue);
1666     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1667     root->appendNewControlValue(proc, Return, Origin(), result32);
1668
1669     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1670 }
1671
1672 void testModImmArgFloat(float a, float b)
1673 {
1674     Procedure proc;
1675     BasicBlock* root = proc.addBlock();
1676     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1677         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1678     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1679     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1680     Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue, floatValue);
1681     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1682     root->appendNewControlValue(proc, Return, Origin(), result32);
1683
1684     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1685 }
1686
1687 void testModImmsFloat(float a, float b)
1688 {
1689     Procedure proc;
1690     BasicBlock* root = proc.addBlock();
1691     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1692     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1693     Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue1, constValue2);
1694     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1695     root->appendNewControlValue(proc, Return, Origin(), result32);
1696
1697     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1698 }
1699
1700 void testDivArgFloatWithUselessDoubleConversion(float a)
1701 {
1702     Procedure proc;
1703     BasicBlock* root = proc.addBlock();
1704     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1705         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1706     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1707     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1708     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble, asDouble);
1709     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1710     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1711     root->appendNewControlValue(proc, Return, Origin(), result32);
1712
1713     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a)));
1714 }
1715
1716 void testDivArgsFloatWithUselessDoubleConversion(float a, float b)
1717 {
1718     Procedure proc;
1719     BasicBlock* root = proc.addBlock();
1720     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1721         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1722     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1723         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1724     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1725     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1726     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1727     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1728     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1729     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1730     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1731     root->appendNewControlValue(proc, Return, Origin(), result32);
1732
1733     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1734 }
1735
1736 void testDivArgsFloatWithEffectfulDoubleConversion(float a, float b)
1737 {
1738     Procedure proc;
1739     BasicBlock* root = proc.addBlock();
1740     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1741         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1742     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1743         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1744     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1745     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1746     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1747     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1748     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1749     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1750     Value* doubleDivress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1751     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleDivress);
1752     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1753     root->appendNewControlValue(proc, Return, Origin(), result32);
1754
1755     double effect = 0;
1756     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a / b)));
1757     CHECK(isIdentical(effect, static_cast<double>(a) / static_cast<double>(b)));
1758 }
1759
1760 void testUDivArgsInt32(uint32_t a, uint32_t b)
1761 {
1762     // UDiv with denominator == 0 is invalid.
1763     if (!b)
1764         return;
1765
1766     Procedure proc;
1767     BasicBlock* root = proc.addBlock();
1768     Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
1769         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1770     Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
1771         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1772     Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
1773     root->appendNew<Value>(proc, Return, Origin(), result);
1774
1775     CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a / b);
1776 }
1777
1778 void testUDivArgsInt64(uint64_t a, uint64_t b)
1779 {
1780     // UDiv with denominator == 0 is invalid.
1781     if (!b)
1782         return;
1783
1784     Procedure proc;
1785     BasicBlock* root = proc.addBlock();
1786     Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1787     Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1788     Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
1789     root->appendNew<Value>(proc, Return, Origin(), result);
1790
1791     CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a / b);
1792 }
1793
1794 void testUModArgsInt32(uint32_t a, uint32_t b)
1795 {
1796     // UMod with denominator == 0 is invalid.
1797     if (!b)
1798         return;
1799
1800     Procedure proc;
1801     BasicBlock* root = proc.addBlock();
1802     Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
1803         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1804     Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
1805         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1806     Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
1807     root->appendNew<Value>(proc, Return, Origin(), result);
1808
1809     CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a % b);
1810 }
1811
1812 void testUModArgsInt64(uint64_t a, uint64_t b)
1813 {
1814     // UMod with denominator == 0 is invalid.
1815     if (!b)
1816         return;
1817
1818     Procedure proc;
1819     BasicBlock* root = proc.addBlock();
1820     Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1821     Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1822     Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
1823     root->appendNew<Value>(proc, Return, Origin(), result);
1824     
1825     CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a % b);
1826 }
1827
1828 void testSubArg(int a)
1829 {
1830     Procedure proc;
1831     BasicBlock* root = proc.addBlock();
1832     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1833     root->appendNewControlValue(
1834         proc, Return, Origin(),
1835         root->appendNew<Value>(proc, Sub, Origin(), value, value));
1836
1837     CHECK(!compileAndRun<int>(proc, a));
1838 }
1839
1840 void testSubArgs(int a, int b)
1841 {
1842     Procedure proc;
1843     BasicBlock* root = proc.addBlock();
1844     root->appendNewControlValue(
1845         proc, Return, Origin(),
1846         root->appendNew<Value>(
1847             proc, Sub, Origin(),
1848             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1849             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
1850
1851     CHECK(compileAndRun<int>(proc, a, b) == a - b);
1852 }
1853
1854 void testSubArgImm(int64_t a, int64_t b)
1855 {
1856     Procedure proc;
1857     BasicBlock* root = proc.addBlock();
1858     root->appendNewControlValue(
1859         proc, Return, Origin(),
1860         root->appendNew<Value>(
1861             proc, Sub, Origin(),
1862             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1863             root->appendNew<Const64Value>(proc, Origin(), b)));
1864
1865     CHECK(compileAndRun<int64_t>(proc, a) == a - b);
1866 }
1867
1868 void testNegValueSubOne(int a)
1869 {
1870     Procedure proc;
1871     BasicBlock* root = proc.addBlock();
1872     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1873     Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
1874         root->appendNew<Const64Value>(proc, Origin(), 0),
1875         argument);
1876     Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
1877         negArgument,
1878         root->appendNew<Const64Value>(proc, Origin(), 1));
1879     root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne);
1880     CHECK(compileAndRun<int>(proc, a) == -a - 1);
1881 }
1882
1883 void testSubImmArg(int a, int b)
1884 {
1885     Procedure proc;
1886     BasicBlock* root = proc.addBlock();
1887     root->appendNewControlValue(
1888         proc, Return, Origin(),
1889         root->appendNew<Value>(
1890             proc, Sub, Origin(),
1891             root->appendNew<Const64Value>(proc, Origin(), a),
1892             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1893
1894     CHECK(compileAndRun<int>(proc, b) == a - b);
1895 }
1896
1897 void testSubArgMem(int64_t a, int64_t b)
1898 {
1899     Procedure proc;
1900     BasicBlock* root = proc.addBlock();
1901     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1902     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1903     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1904         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1905         load);
1906     root->appendNewControlValue(proc, Return, Origin(), result);
1907
1908     CHECK(compileAndRun<int64_t>(proc, a, &b) == a - b);
1909 }
1910
1911 void testSubMemArg(int64_t a, int64_t b)
1912 {
1913     Procedure proc;
1914     BasicBlock* root = proc.addBlock();
1915     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1916     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1917     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1918         load,
1919         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1920     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1921     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1922
1923     int64_t inputOutput = a;
1924     CHECK(!compileAndRun<int64_t>(proc, &inputOutput, b));
1925     CHECK(inputOutput == a - b);
1926 }
1927
1928 void testSubImmMem(int64_t a, int64_t b)
1929 {
1930     Procedure proc;
1931     BasicBlock* root = proc.addBlock();
1932     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1933     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1934     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1935         root->appendNew<Const64Value>(proc, Origin(), a),
1936         load);
1937     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1938     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1939
1940     int64_t inputOutput = b;
1941     CHECK(!compileAndRun<int>(proc, &inputOutput));
1942     CHECK(inputOutput == a - b);
1943 }
1944
1945 void testSubMemImm(int64_t a, int64_t b)
1946 {
1947     Procedure proc;
1948     BasicBlock* root = proc.addBlock();
1949     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1950     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1951     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1952         load,
1953         root->appendNew<Const64Value>(proc, Origin(), b));
1954     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1955     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1956
1957     int64_t inputOutput = a;
1958     CHECK(!compileAndRun<int>(proc, &inputOutput));
1959     CHECK(inputOutput == a - b);
1960 }
1961
1962
1963 void testSubArgs32(int a, int b)
1964 {
1965     Procedure proc;
1966     BasicBlock* root = proc.addBlock();
1967     root->appendNewControlValue(
1968         proc, Return, Origin(),
1969         root->appendNew<Value>(
1970             proc, Sub, Origin(),
1971             root->appendNew<Value>(
1972                 proc, Trunc, Origin(),
1973                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1974             root->appendNew<Value>(
1975                 proc, Trunc, Origin(),
1976                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1977
1978     CHECK(compileAndRun<int>(proc, a, b) == a - b);
1979 }
1980
1981 void testSubArgImm32(int a, int b)
1982 {
1983     Procedure proc;
1984     BasicBlock* root = proc.addBlock();
1985     root->appendNewControlValue(
1986         proc, Return, Origin(),
1987         root->appendNew<Value>(
1988             proc, Sub, Origin(),
1989             root->appendNew<Value>(
1990                 proc, Trunc, Origin(),
1991                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1992             root->appendNew<Const32Value>(proc, Origin(), b)));
1993
1994     CHECK(compileAndRun<int>(proc, a) == a - b);
1995 }
1996
1997 void testSubImmArg32(int a, int b)
1998 {
1999     Procedure proc;
2000     BasicBlock* root = proc.addBlock();
2001     root->appendNewControlValue(
2002         proc, Return, Origin(),
2003         root->appendNew<Value>(
2004             proc, Sub, Origin(),
2005             root->appendNew<Const32Value>(proc, Origin(), a),
2006             root->appendNew<Value>(
2007                 proc, Trunc, Origin(),
2008                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2009
2010     CHECK(compileAndRun<int>(proc, b) == a - b);
2011 }
2012
2013 void testSubMemArg32(int32_t a, int32_t b)
2014 {
2015     Procedure proc;
2016     BasicBlock* root = proc.addBlock();
2017     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2018     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2019     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2020         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2021     Value* result = root->appendNew<Value>(proc, Sub, Origin(), load, argument);
2022     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2023     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2024
2025     int32_t inputOutput = a;
2026     CHECK(!compileAndRun<int32_t>(proc, &inputOutput, b));
2027     CHECK(inputOutput == a - b);
2028 }
2029
2030 void testSubArgMem32(int32_t a, int32_t b)
2031 {
2032     Procedure proc;
2033     BasicBlock* root = proc.addBlock();
2034     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2035     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2036     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2037         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2038     Value* result = root->appendNew<Value>(proc, Sub, Origin(), argument, load);
2039     root->appendNewControlValue(proc, Return, Origin(), result);
2040
2041     CHECK(compileAndRun<int32_t>(proc, a, &b) == a - b);
2042 }
2043
2044 void testSubImmMem32(int32_t a, int32_t b)
2045 {
2046     Procedure proc;
2047     BasicBlock* root = proc.addBlock();
2048     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2049     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2050     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2051         root->appendNew<Const32Value>(proc, Origin(), a),
2052         load);
2053     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2054     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2055
2056     int32_t inputOutput = b;
2057     CHECK(!compileAndRun<int>(proc, &inputOutput));
2058     CHECK(inputOutput == a - b);
2059 }
2060
2061 void testSubMemImm32(int32_t a, int32_t b)
2062 {
2063     Procedure proc;
2064     BasicBlock* root = proc.addBlock();
2065     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2066     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2067     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2068         load,
2069         root->appendNew<Const32Value>(proc, Origin(), b));
2070     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2071     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2072
2073     int32_t inputOutput = a;
2074     CHECK(!compileAndRun<int>(proc, &inputOutput));
2075     CHECK(inputOutput == a - b);
2076 }
2077
2078 void testNegValueSubOne32(int a)
2079 {
2080     Procedure proc;
2081     BasicBlock* root = proc.addBlock();
2082     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2083         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2084     Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
2085         root->appendNew<Const32Value>(proc, Origin(), 0),
2086         argument);
2087     Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
2088         negArgument,
2089         root->appendNew<Const32Value>(proc, Origin(), 1));
2090     root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne);
2091     CHECK(compileAndRun<int>(proc, a) == -a - 1);
2092 }
2093
2094 void testSubArgDouble(double a)
2095 {
2096     Procedure proc;
2097     BasicBlock* root = proc.addBlock();
2098     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2099     root->appendNewControlValue(
2100         proc, Return, Origin(),
2101         root->appendNew<Value>(proc, Sub, Origin(), value, value));
2102
2103     CHECK(isIdentical(compileAndRun<double>(proc, a), a - a));
2104 }
2105
2106 void testSubArgsDouble(double a, double b)
2107 {
2108     Procedure proc;
2109     BasicBlock* root = proc.addBlock();
2110     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2111     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2112     root->appendNewControlValue(
2113         proc, Return, Origin(),
2114         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2115
2116     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a - b));
2117 }
2118
2119 void testSubArgImmDouble(double a, double b)
2120 {
2121     Procedure proc;
2122     BasicBlock* root = proc.addBlock();
2123     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2124     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2125     root->appendNewControlValue(
2126         proc, Return, Origin(),
2127         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2128
2129     CHECK(isIdentical(compileAndRun<double>(proc, a), a - b));
2130 }
2131
2132 void testSubImmArgDouble(double a, double b)
2133 {
2134     Procedure proc;
2135     BasicBlock* root = proc.addBlock();
2136     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2137     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2138     root->appendNewControlValue(
2139         proc, Return, Origin(),
2140         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2141
2142     CHECK(isIdentical(compileAndRun<double>(proc, b), a - b));
2143 }
2144
2145 void testSubImmsDouble(double a, double b)
2146 {
2147     Procedure proc;
2148     BasicBlock* root = proc.addBlock();
2149     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2150     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2151     root->appendNewControlValue(
2152         proc, Return, Origin(),
2153         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2154     
2155     CHECK(isIdentical(compileAndRun<double>(proc), a - b));
2156 }
2157
2158 void testSubArgFloat(float a)
2159 {
2160     Procedure proc;
2161     BasicBlock* root = proc.addBlock();
2162     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2163         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2164     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2165     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, floatValue);
2166     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2167     root->appendNewControlValue(proc, Return, Origin(), result32);
2168
2169
2170     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
2171 }
2172
2173 void testSubArgsFloat(float a, float b)
2174 {
2175     Procedure proc;
2176     BasicBlock* root = proc.addBlock();
2177     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2178         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2179     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2180         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2181     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2182     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2183     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue1, floatValue2);
2184     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2185     root->appendNewControlValue(proc, Return, Origin(), result32);
2186
2187     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2188 }
2189
2190 void testSubArgImmFloat(float a, float b)
2191 {
2192     Procedure proc;
2193     BasicBlock* root = proc.addBlock();
2194     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2195         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2196     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2197     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2198     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, constValue);
2199     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2200     root->appendNewControlValue(proc, Return, Origin(), result32);
2201
2202     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - b)));
2203 }
2204
2205 void testSubImmArgFloat(float a, float b)
2206 {
2207     Procedure proc;
2208     BasicBlock* root = proc.addBlock();
2209     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2210         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2211     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2212     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2213     Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue, floatValue);
2214     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2215     root->appendNewControlValue(proc, Return, Origin(), result32);
2216
2217     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2218 }
2219
2220 void testSubImmsFloat(float a, float b)
2221 {
2222     Procedure proc;
2223     BasicBlock* root = proc.addBlock();
2224     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2225     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2226     Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue1, constValue2);
2227     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2228     root->appendNewControlValue(proc, Return, Origin(), result32);
2229
2230     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a - b)));
2231 }
2232
2233 void testSubArgFloatWithUselessDoubleConversion(float a)
2234 {
2235     Procedure proc;
2236     BasicBlock* root = proc.addBlock();
2237     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
2238         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2239     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
2240     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2241     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble, asDouble);
2242     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2243     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2244     root->appendNewControlValue(proc, Return, Origin(), result32);
2245
2246     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
2247 }
2248
2249 void testSubArgsFloatWithUselessDoubleConversion(float a, float b)
2250 {
2251     Procedure proc;
2252     BasicBlock* root = proc.addBlock();
2253     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2254         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2255     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2256         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2257     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2258     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2259     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
2260     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
2261     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
2262     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2263     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2264     root->appendNewControlValue(proc, Return, Origin(), result32);
2265
2266     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2267 }
2268
2269 void testSubArgsFloatWithEffectfulDoubleConversion(float a, float b)
2270 {
2271     Procedure proc;
2272     BasicBlock* root = proc.addBlock();
2273     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2274         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2275     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2276         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2277     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2278     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2279     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
2280     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
2281     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
2282     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2283     Value* doubleSubress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2284     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleSubress);
2285     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2286     root->appendNewControlValue(proc, Return, Origin(), result32);
2287
2288     double effect = 0;
2289     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a - b)));
2290     CHECK(isIdentical(effect, static_cast<double>(a) - static_cast<double>(b)));
2291 }
2292
2293 void testTernarySubInstructionSelection(B3::Opcode valueModifier, Type valueType, Air::Opcode expectedOpcode)
2294 {
2295     Procedure proc;
2296     BasicBlock* root = proc.addBlock();
2297
2298     Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2299     Value* right = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2300
2301     if (valueModifier == Trunc) {
2302         left = root->appendNew<Value>(proc, valueModifier, valueType, Origin(), left);
2303         right = root->appendNew<Value>(proc, valueModifier, valueType, Origin(), right);
2304     }
2305
2306     root->appendNewControlValue(
2307         proc, Return, Origin(),
2308         root->appendNew<Value>(proc, Sub, Origin(), left, right));
2309
2310     lowerToAirForTesting(proc);
2311
2312     auto block = proc.code()[0];
2313     unsigned numberOfSubInstructions = 0;
2314     for (auto instruction : *block) {
2315         if (instruction.kind.opcode == expectedOpcode) {
2316             CHECK_EQ(instruction.args.size(), 3ul);
2317             CHECK_EQ(instruction.args[0].kind(), Air::Arg::Tmp);
2318             CHECK_EQ(instruction.args[1].kind(), Air::Arg::Tmp);
2319             CHECK_EQ(instruction.args[2].kind(), Air::Arg::Tmp);
2320             numberOfSubInstructions++;
2321         }
2322     }
2323     CHECK_EQ(numberOfSubInstructions, 1ul);
2324 }
2325
2326 void testNegDouble(double a)
2327 {
2328     Procedure proc;
2329     BasicBlock* root = proc.addBlock();
2330     root->appendNewControlValue(
2331         proc, Return, Origin(),
2332         root->appendNew<Value>(
2333             proc, Neg, Origin(),
2334             root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
2335
2336     CHECK(isIdentical(compileAndRun<double>(proc, a), -a));
2337 }
2338
2339 void testNegFloat(float a)
2340 {
2341     Procedure proc;
2342     BasicBlock* root = proc.addBlock();
2343     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2344         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2345     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2346     root->appendNewControlValue(
2347         proc, Return, Origin(),
2348         root->appendNew<Value>(proc, Neg, Origin(), floatValue));
2349
2350     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), -a));
2351 }
2352
2353 void testNegFloatWithUselessDoubleConversion(float a)
2354 {
2355     Procedure proc;
2356     BasicBlock* root = proc.addBlock();
2357     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
2358         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2359     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
2360     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2361     Value* result = root->appendNew<Value>(proc, Neg, Origin(), asDouble);
2362     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2363     root->appendNewControlValue(proc, Return, Origin(), floatResult);
2364
2365     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), -a));
2366 }
2367
2368 void testBitAndArgs(int64_t a, int64_t b)
2369 {
2370     Procedure proc;
2371     BasicBlock* root = proc.addBlock();
2372     root->appendNewControlValue(
2373         proc, Return, Origin(),
2374         root->appendNew<Value>(
2375             proc, BitAnd, Origin(),
2376             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2377             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2378
2379     CHECK(compileAndRun<int64_t>(proc, a, b) == (a & b));
2380 }
2381
2382 void testBitAndSameArg(int64_t a)
2383 {
2384     Procedure proc;
2385     BasicBlock* root = proc.addBlock();
2386     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2387     root->appendNewControlValue(
2388         proc, Return, Origin(),
2389         root->appendNew<Value>(
2390             proc, BitAnd, Origin(),
2391             argument,
2392             argument));
2393
2394     CHECK(compileAndRun<int64_t>(proc, a) == a);
2395 }
2396
2397 void testBitAndImms(int64_t a, int64_t b)
2398 {
2399     Procedure proc;
2400     BasicBlock* root = proc.addBlock();
2401     root->appendNewControlValue(
2402         proc, Return, Origin(),
2403         root->appendNew<Value>(
2404             proc, BitAnd, Origin(),
2405             root->appendNew<Const64Value>(proc, Origin(), a),
2406             root->appendNew<Const64Value>(proc, Origin(), b)));
2407
2408     CHECK(compileAndRun<int64_t>(proc) == (a & b));
2409 }
2410
2411 void testBitAndArgImm(int64_t a, int64_t b)
2412 {
2413     Procedure proc;
2414     BasicBlock* root = proc.addBlock();
2415     root->appendNewControlValue(
2416         proc, Return, Origin(),
2417         root->appendNew<Value>(
2418             proc, BitAnd, Origin(),
2419             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2420             root->appendNew<Const64Value>(proc, Origin(), b)));
2421
2422     CHECK(compileAndRun<int64_t>(proc, a) == (a & b));
2423 }
2424
2425 void testBitAndImmArg(int64_t a, int64_t b)
2426 {
2427     Procedure proc;
2428     BasicBlock* root = proc.addBlock();
2429     root->appendNewControlValue(
2430         proc, Return, Origin(),
2431         root->appendNew<Value>(
2432             proc, BitAnd, Origin(),
2433             root->appendNew<Const64Value>(proc, Origin(), a),
2434             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2435
2436     CHECK(compileAndRun<int64_t>(proc, b) == (a & b));
2437 }
2438
2439 void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c)
2440 {
2441     Procedure proc;
2442     BasicBlock* root = proc.addBlock();
2443     Value* innerBitAnd = root->appendNew<Value>(
2444         proc, BitAnd, Origin(),
2445         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2446         root->appendNew<Const64Value>(proc, Origin(), b));
2447     root->appendNewControlValue(
2448         proc, Return, Origin(),
2449         root->appendNew<Value>(
2450             proc, BitAnd, Origin(),
2451             innerBitAnd,
2452             root->appendNew<Const64Value>(proc, Origin(), c)));
2453
2454     CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c));
2455 }
2456
2457 void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c)
2458 {
2459     Procedure proc;
2460     BasicBlock* root = proc.addBlock();
2461     Value* innerBitAnd = root->appendNew<Value>(
2462         proc, BitAnd, Origin(),
2463         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2464         root->appendNew<Const64Value>(proc, Origin(), c));
2465     root->appendNewControlValue(
2466         proc, Return, Origin(),
2467         root->appendNew<Value>(
2468             proc, BitAnd, Origin(),
2469             root->appendNew<Const64Value>(proc, Origin(), a),
2470             innerBitAnd));
2471
2472     CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c)));
2473 }
2474
2475 void testBitAndArgs32(int a, int b)
2476 {
2477     Procedure proc;
2478     BasicBlock* root = proc.addBlock();
2479     root->appendNewControlValue(
2480         proc, Return, Origin(),
2481         root->appendNew<Value>(
2482             proc, BitAnd, Origin(),
2483             root->appendNew<Value>(
2484                 proc, Trunc, Origin(),
2485                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2486             root->appendNew<Value>(
2487                 proc, Trunc, Origin(),
2488                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2489
2490     CHECK(compileAndRun<int>(proc, a, b) == (a & b));
2491 }
2492
2493 void testBitAndSameArg32(int a)
2494 {
2495     Procedure proc;
2496     BasicBlock* root = proc.addBlock();
2497     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2498         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2499     root->appendNewControlValue(
2500         proc, Return, Origin(),
2501         root->appendNew<Value>(
2502             proc, BitAnd, Origin(),
2503             argument,
2504             argument));
2505
2506     CHECK(compileAndRun<int>(proc, a) == a);
2507 }
2508
2509 void testBitAndImms32(int a, int b)
2510 {
2511     Procedure proc;
2512     BasicBlock* root = proc.addBlock();
2513     root->appendNewControlValue(
2514         proc, Return, Origin(),
2515         root->appendNew<Value>(
2516             proc, BitAnd, Origin(),
2517             root->appendNew<Const32Value>(proc, Origin(), a),
2518             root->appendNew<Const32Value>(proc, Origin(), b)));
2519
2520     CHECK(compileAndRun<int>(proc) == (a & b));
2521 }
2522
2523 void testBitAndArgImm32(int a, int b)
2524 {
2525     Procedure proc;
2526     BasicBlock* root = proc.addBlock();
2527     root->appendNewControlValue(
2528         proc, Return, Origin(),
2529         root->appendNew<Value>(
2530             proc, BitAnd, Origin(),
2531             root->appendNew<Value>(
2532                 proc, Trunc, Origin(),
2533                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2534             root->appendNew<Const32Value>(proc, Origin(), b)));
2535
2536     CHECK(compileAndRun<int>(proc, a) == (a & b));
2537 }
2538
2539 void testBitAndImmArg32(int a, int b)
2540 {
2541     Procedure proc;
2542     BasicBlock* root = proc.addBlock();
2543     root->appendNewControlValue(
2544         proc, Return, Origin(),
2545         root->appendNew<Value>(
2546             proc, BitAnd, Origin(),
2547             root->appendNew<Const32Value>(proc, Origin(), a),
2548             root->appendNew<Value>(
2549                 proc, Trunc, Origin(),
2550                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2551
2552     CHECK(compileAndRun<int>(proc, b) == (a & b));
2553 }
2554
2555 void testBitAndBitAndArgImmImm32(int a, int b, int c)
2556 {
2557     Procedure proc;
2558     BasicBlock* root = proc.addBlock();
2559     Value* innerBitAnd = root->appendNew<Value>(
2560         proc, BitAnd, Origin(),
2561         root->appendNew<Value>(
2562             proc, Trunc, Origin(),
2563             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2564         root->appendNew<Const32Value>(proc, Origin(), b));
2565     root->appendNewControlValue(
2566         proc, Return, Origin(),
2567         root->appendNew<Value>(
2568             proc, BitAnd, Origin(),
2569             innerBitAnd,
2570             root->appendNew<Const32Value>(proc, Origin(), c)));
2571
2572     CHECK(compileAndRun<int>(proc, a) == ((a & b) & c));
2573 }
2574
2575 void testBitAndImmBitAndArgImm32(int a, int b, int c)
2576 {
2577     Procedure proc;
2578     BasicBlock* root = proc.addBlock();
2579     Value* innerBitAnd = root->appendNew<Value>(
2580         proc, BitAnd, Origin(),
2581         root->appendNew<Value>(
2582             proc, Trunc, Origin(),
2583             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2584         root->appendNew<Const32Value>(proc, Origin(), c));
2585     root->appendNewControlValue(
2586         proc, Return, Origin(),
2587         root->appendNew<Value>(
2588             proc, BitAnd, Origin(),
2589             root->appendNew<Const32Value>(proc, Origin(), a),
2590             innerBitAnd));
2591
2592     CHECK(compileAndRun<int>(proc, b) == (a & (b & c)));
2593 }
2594
2595 void testBitAndWithMaskReturnsBooleans(int64_t a, int64_t b)
2596 {
2597     Procedure proc;
2598     BasicBlock* root = proc.addBlock();
2599     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2600     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2601     Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg0, arg1);
2602     Value* maskedEqual = root->appendNew<Value>(proc, BitAnd, Origin(),
2603         root->appendNew<Const32Value>(proc, Origin(), 0x5),
2604         equal);
2605     Value* inverted = root->appendNew<Value>(proc, BitXor, Origin(),
2606         root->appendNew<Const32Value>(proc, Origin(), 0x1),
2607         maskedEqual);
2608     Value* select = root->appendNew<Value>(proc, Select, Origin(), inverted,
2609         root->appendNew<Const64Value>(proc, Origin(), 42),
2610         root->appendNew<Const64Value>(proc, Origin(), -5));
2611
2612     root->appendNewControlValue(proc, Return, Origin(), select);
2613
2614     int64_t expected = (a == b) ? -5 : 42;
2615     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
2616 }
2617
2618 double bitAndDouble(double a, double b)
2619 {
2620     return bitwise_cast<double>(bitwise_cast<uint64_t>(a) & bitwise_cast<uint64_t>(b));
2621 }
2622
2623 void testBitAndArgDouble(double a)
2624 {
2625     Procedure proc;
2626     BasicBlock* root = proc.addBlock();
2627     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2628     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2629     root->appendNewControlValue(proc, Return, Origin(), result);
2630
2631     CHECK(isIdentical(compileAndRun<double>(proc, a), bitAndDouble(a, a)));
2632 }
2633
2634 void testBitAndArgsDouble(double a, double b)
2635 {
2636     Procedure proc;
2637     BasicBlock* root = proc.addBlock();
2638     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2639     Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2640     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2641     root->appendNewControlValue(proc, Return, Origin(), result);
2642
2643     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2644 }
2645
2646 void testBitAndArgImmDouble(double a, double b)
2647 {
2648     Procedure proc;
2649     BasicBlock* root = proc.addBlock();
2650     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2651     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2652     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2653     root->appendNewControlValue(proc, Return, Origin(), result);
2654
2655     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2656 }
2657
2658 void testBitAndImmsDouble(double a, double b)
2659 {
2660     Procedure proc;
2661     BasicBlock* root = proc.addBlock();
2662     Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2663     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2664     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2665     root->appendNewControlValue(proc, Return, Origin(), result);
2666
2667     CHECK(isIdentical(compileAndRun<double>(proc), bitAndDouble(a, b)));
2668 }
2669
2670 float bitAndFloat(float a, float b)
2671 {
2672     return bitwise_cast<float>(bitwise_cast<uint32_t>(a) & bitwise_cast<uint32_t>(b));
2673 }
2674
2675 void testBitAndArgFloat(float a)
2676 {
2677     Procedure proc;
2678     BasicBlock* root = proc.addBlock();
2679     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2680         root->appendNew<Value>(proc, Trunc, Origin(),
2681             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2682     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2683     root->appendNewControlValue(proc, Return, Origin(), result);
2684
2685     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitAndFloat(a, a)));
2686 }
2687
2688 void testBitAndArgsFloat(float a, float b)
2689 {
2690     Procedure proc;
2691     BasicBlock* root = proc.addBlock();
2692     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2693         root->appendNew<Value>(proc, Trunc, Origin(),
2694             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2695     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2696         root->appendNew<Value>(proc, Trunc, Origin(),
2697             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2698     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2699     root->appendNewControlValue(proc, Return, Origin(), result);
2700
2701     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2702 }
2703
2704 void testBitAndArgImmFloat(float a, float b)
2705 {
2706     Procedure proc;
2707     BasicBlock* root = proc.addBlock();
2708     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2709         root->appendNew<Value>(proc, Trunc, Origin(),
2710             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2711     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2712     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2713     root->appendNewControlValue(proc, Return, Origin(), result);
2714
2715     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2716 }
2717
2718 void testBitAndImmsFloat(float a, float b)
2719 {
2720     Procedure proc;
2721     BasicBlock* root = proc.addBlock();
2722     Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2723     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2724     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2725     root->appendNewControlValue(proc, Return, Origin(), result);
2726
2727     CHECK(isIdentical(compileAndRun<float>(proc), bitAndFloat(a, b)));
2728 }
2729
2730 void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b)
2731 {
2732     Procedure proc;
2733     BasicBlock* root = proc.addBlock();
2734     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2735         root->appendNew<Value>(proc, Trunc, Origin(),
2736             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2737     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2738         root->appendNew<Value>(proc, Trunc, Origin(),
2739             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2740     Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
2741     Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
2742     Value* doubleResult = root->appendNew<Value>(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble);
2743     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
2744     root->appendNewControlValue(proc, Return, Origin(), floatResult);
2745
2746     double doubleA = a;
2747     double doubleB = b;
2748     float expected = static_cast<float>(bitAndDouble(doubleA, doubleB));
2749     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
2750 }
2751
2752 void testBitOrArgs(int64_t a, int64_t b)
2753 {
2754     Procedure proc;
2755     BasicBlock* root = proc.addBlock();
2756     root->appendNewControlValue(
2757         proc, Return, Origin(),
2758         root->appendNew<Value>(
2759             proc, BitOr, Origin(),
2760             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2761             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2762
2763     CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b));
2764 }
2765
2766 void testBitOrSameArg(int64_t a)
2767 {
2768     Procedure proc;
2769     BasicBlock* root = proc.addBlock();
2770     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2771     root->appendNewControlValue(
2772         proc, Return, Origin(),
2773         root->appendNew<Value>(
2774             proc, BitOr, Origin(),
2775             argument,
2776             argument));
2777
2778     CHECK(compileAndRun<int64_t>(proc, a) == a);
2779 }
2780
2781 void testBitOrImms(int64_t a, int64_t b)
2782 {
2783     Procedure proc;
2784     BasicBlock* root = proc.addBlock();
2785     root->appendNewControlValue(
2786         proc, Return, Origin(),
2787         root->appendNew<Value>(
2788             proc, BitOr, Origin(),
2789             root->appendNew<Const64Value>(proc, Origin(), a),
2790             root->appendNew<Const64Value>(proc, Origin(), b)));
2791
2792     CHECK(compileAndRun<int64_t>(proc) == (a | b));
2793 }
2794
2795 void testBitOrArgImm(int64_t a, int64_t b)
2796 {
2797     Procedure proc;
2798     BasicBlock* root = proc.addBlock();
2799     root->appendNewControlValue(
2800         proc, Return, Origin(),
2801         root->appendNew<Value>(
2802             proc, BitOr, Origin(),
2803             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2804             root->appendNew<Const64Value>(proc, Origin(), b)));
2805
2806     CHECK(compileAndRun<int64_t>(proc, a) == (a | b));
2807 }
2808
2809 void testBitOrImmArg(int64_t a, int64_t b)
2810 {
2811     Procedure proc;
2812     BasicBlock* root = proc.addBlock();
2813     root->appendNewControlValue(
2814         proc, Return, Origin(),
2815         root->appendNew<Value>(
2816             proc, BitOr, Origin(),
2817             root->appendNew<Const64Value>(proc, Origin(), a),
2818             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2819
2820     CHECK(compileAndRun<int64_t>(proc, b) == (a | b));
2821 }
2822
2823 void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c)
2824 {
2825     Procedure proc;
2826     BasicBlock* root = proc.addBlock();
2827     Value* innerBitOr = root->appendNew<Value>(
2828         proc, BitOr, Origin(),
2829         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2830         root->appendNew<Const64Value>(proc, Origin(), b));
2831     root->appendNewControlValue(
2832         proc, Return, Origin(),
2833         root->appendNew<Value>(
2834             proc, BitOr, Origin(),
2835             innerBitOr,
2836             root->appendNew<Const64Value>(proc, Origin(), c)));
2837
2838     CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c));
2839 }
2840
2841 void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c)
2842 {
2843     Procedure proc;
2844     BasicBlock* root = proc.addBlock();
2845     Value* innerBitOr = root->appendNew<Value>(
2846         proc, BitOr, Origin(),
2847         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2848         root->appendNew<Const64Value>(proc, Origin(), c));
2849     root->appendNewControlValue(
2850         proc, Return, Origin(),
2851         root->appendNew<Value>(
2852             proc, BitOr, Origin(),
2853             root->appendNew<Const64Value>(proc, Origin(), a),
2854             innerBitOr));
2855
2856     CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c)));
2857 }
2858
2859 void testBitOrArgs32(int a, int b)
2860 {
2861     Procedure proc;
2862     BasicBlock* root = proc.addBlock();
2863     root->appendNewControlValue(
2864         proc, Return, Origin(),
2865         root->appendNew<Value>(
2866             proc, BitOr, Origin(),
2867             root->appendNew<Value>(
2868                 proc, Trunc, Origin(),
2869                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2870             root->appendNew<Value>(
2871                 proc, Trunc, Origin(),
2872                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2873
2874     CHECK(compileAndRun<int>(proc, a, b) == (a | b));
2875 }
2876
2877 void testBitOrSameArg32(int a)
2878 {
2879     Procedure proc;
2880     BasicBlock* root = proc.addBlock();
2881     Value* argument = root->appendNew<Value>(
2882         proc, Trunc, Origin(),
2883             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2884     root->appendNewControlValue(
2885         proc, Return, Origin(),
2886         root->appendNew<Value>(
2887             proc, BitOr, Origin(),
2888             argument,
2889             argument));
2890
2891     CHECK(compileAndRun<int>(proc, a) == a);
2892 }
2893
2894 void testBitOrImms32(int a, int b)
2895 {
2896     Procedure proc;
2897     BasicBlock* root = proc.addBlock();
2898     root->appendNewControlValue(
2899         proc, Return, Origin(),
2900         root->appendNew<Value>(
2901             proc, BitOr, Origin(),
2902             root->appendNew<Const32Value>(proc, Origin(), a),
2903             root->appendNew<Const32Value>(proc, Origin(), b)));
2904
2905     CHECK(compileAndRun<int>(proc) == (a | b));
2906 }
2907
2908 void testBitOrArgImm32(int a, int b)
2909 {
2910     Procedure proc;
2911     BasicBlock* root = proc.addBlock();
2912     root->appendNewControlValue(
2913         proc, Return, Origin(),
2914         root->appendNew<Value>(
2915             proc, BitOr, Origin(),
2916             root->appendNew<Value>(
2917                 proc, Trunc, Origin(),
2918                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2919             root->appendNew<Const32Value>(proc, Origin(), b)));
2920
2921     CHECK(compileAndRun<int>(proc, a) == (a | b));
2922 }
2923
2924 void testBitOrImmArg32(int a, int b)
2925 {
2926     Procedure proc;
2927     BasicBlock* root = proc.addBlock();
2928     root->appendNewControlValue(
2929         proc, Return, Origin(),
2930         root->appendNew<Value>(
2931             proc, BitOr, Origin(),
2932             root->appendNew<Const32Value>(proc, Origin(), a),
2933             root->appendNew<Value>(
2934                 proc, Trunc, Origin(),
2935                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2936
2937     CHECK(compileAndRun<int>(proc, b) == (a | b));
2938 }
2939
2940 void testBitOrBitOrArgImmImm32(int a, int b, int c)
2941 {
2942     Procedure proc;
2943     BasicBlock* root = proc.addBlock();
2944     Value* innerBitOr = root->appendNew<Value>(
2945         proc, BitOr, Origin(),
2946         root->appendNew<Value>(
2947             proc, Trunc, Origin(),
2948             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2949         root->appendNew<Const32Value>(proc, Origin(), b));
2950     root->appendNewControlValue(
2951         proc, Return, Origin(),
2952         root->appendNew<Value>(
2953             proc, BitOr, Origin(),
2954             innerBitOr,
2955             root->appendNew<Const32Value>(proc, Origin(), c)));
2956
2957     CHECK(compileAndRun<int>(proc, a) == ((a | b) | c));
2958 }
2959
2960 void testBitOrImmBitOrArgImm32(int a, int b, int c)
2961 {
2962     Procedure proc;
2963     BasicBlock* root = proc.addBlock();
2964     Value* innerBitOr = root->appendNew<Value>(
2965         proc, BitOr, Origin(),
2966         root->appendNew<Value>(
2967             proc, Trunc, Origin(),
2968             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2969         root->appendNew<Const32Value>(proc, Origin(), c));
2970     root->appendNewControlValue(
2971         proc, Return, Origin(),
2972         root->appendNew<Value>(
2973             proc, BitOr, Origin(),
2974             root->appendNew<Const32Value>(proc, Origin(), a),
2975             innerBitOr));
2976
2977     CHECK(compileAndRun<int>(proc, b) == (a | (b | c)));
2978 }
2979
2980 void testBitXorArgs(int64_t a, int64_t b)
2981 {
2982     Procedure proc;
2983     BasicBlock* root = proc.addBlock();
2984     root->appendNewControlValue(
2985         proc, Return, Origin(),
2986         root->appendNew<Value>(
2987             proc, BitXor, Origin(),
2988             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2989             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2990
2991     CHECK(compileAndRun<int64_t>(proc, a, b) == (a ^ b));
2992 }
2993
2994 void testBitXorSameArg(int64_t a)
2995 {
2996     Procedure proc;
2997     BasicBlock* root = proc.addBlock();
2998     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2999     root->appendNewControlValue(
3000         proc, Return, Origin(),
3001         root->appendNew<Value>(
3002             proc, BitXor, Origin(),
3003             argument,
3004             argument));
3005
3006     CHECK(!compileAndRun<int64_t>(proc, a));
3007 }
3008
3009 void testBitXorImms(int64_t a, int64_t b)
3010 {
3011     Procedure proc;
3012     BasicBlock* root = proc.addBlock();
3013     root->appendNewControlValue(
3014         proc, Return, Origin(),
3015         root->appendNew<Value>(
3016             proc, BitXor, Origin(),
3017             root->appendNew<Const64Value>(proc, Origin(), a),
3018             root->appendNew<Const64Value>(proc, Origin(), b)));
3019
3020     CHECK(compileAndRun<int64_t>(proc) == (a ^ b));
3021 }
3022
3023 void testBitXorArgImm(int64_t a, int64_t b)
3024 {
3025     Procedure proc;
3026     BasicBlock* root = proc.addBlock();
3027     root->appendNewControlValue(
3028         proc, Return, Origin(),
3029         root->appendNew<Value>(
3030             proc, BitXor, Origin(),
3031             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3032             root->appendNew<Const64Value>(proc, Origin(), b)));
3033
3034     CHECK(compileAndRun<int64_t>(proc, a) == (a ^ b));
3035 }
3036
3037 void testBitXorImmArg(int64_t a, int64_t b)
3038 {
3039     Procedure proc;
3040     BasicBlock* root = proc.addBlock();
3041     root->appendNewControlValue(
3042         proc, Return, Origin(),
3043         root->appendNew<Value>(
3044             proc, BitXor, Origin(),
3045             root->appendNew<Const64Value>(proc, Origin(), a),
3046             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3047
3048     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ b));
3049 }
3050
3051 void testBitXorBitXorArgImmImm(int64_t a, int64_t b, int64_t c)
3052 {
3053     Procedure proc;
3054     BasicBlock* root = proc.addBlock();
3055     Value* innerBitXor = root->appendNew<Value>(
3056         proc, BitXor, Origin(),
3057         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3058         root->appendNew<Const64Value>(proc, Origin(), b));
3059     root->appendNewControlValue(
3060         proc, Return, Origin(),
3061         root->appendNew<Value>(
3062             proc, BitXor, Origin(),
3063             innerBitXor,
3064             root->appendNew<Const64Value>(proc, Origin(), c)));
3065
3066     CHECK(compileAndRun<int64_t>(proc, a) == ((a ^ b) ^ c));
3067 }
3068
3069 void testBitXorImmBitXorArgImm(int64_t a, int64_t b, int64_t c)
3070 {
3071     Procedure proc;
3072     BasicBlock* root = proc.addBlock();
3073     Value* innerBitXor = root->appendNew<Value>(
3074         proc, BitXor, Origin(),
3075         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3076         root->appendNew<Const64Value>(proc, Origin(), c));
3077     root->appendNewControlValue(
3078         proc, Return, Origin(),
3079         root->appendNew<Value>(
3080             proc, BitXor, Origin(),
3081             root->appendNew<Const64Value>(proc, Origin(), a),
3082             innerBitXor));
3083
3084     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ (b ^ c)));
3085 }
3086
3087 void testBitXorArgs32(int a, int b)
3088 {
3089     Procedure proc;
3090     BasicBlock* root = proc.addBlock();
3091     root->appendNewControlValue(
3092         proc, Return, Origin(),
3093         root->appendNew<Value>(
3094             proc, BitXor, Origin(),
3095             root->appendNew<Value>(
3096                 proc, Trunc, Origin(),
3097                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3098             root->appendNew<Value>(
3099                 proc, Trunc, Origin(),
3100                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3101
3102     CHECK(compileAndRun<int>(proc, a, b) == (a ^ b));
3103 }
3104
3105 void testBitXorSameArg32(int a)
3106 {
3107     Procedure proc;
3108     BasicBlock* root = proc.addBlock();
3109     Value* argument = root->appendNew<Value>(
3110         proc, Trunc, Origin(),
3111             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3112     root->appendNewControlValue(
3113         proc, Return, Origin(),
3114         root->appendNew<Value>(
3115             proc, BitXor, Origin(),
3116             argument,
3117             argument));
3118
3119     CHECK(!compileAndRun<int>(proc, a));
3120 }
3121
3122 void testBitXorImms32(int a, int b)
3123 {
3124     Procedure proc;
3125     BasicBlock* root = proc.addBlock();
3126     root->appendNewControlValue(
3127         proc, Return, Origin(),
3128         root->appendNew<Value>(
3129             proc, BitXor, Origin(),
3130             root->appendNew<Const32Value>(proc, Origin(), a),
3131             root->appendNew<Const32Value>(proc, Origin(), b)));
3132
3133     CHECK(compileAndRun<int>(proc) == (a ^ b));
3134 }
3135
3136 void testBitXorArgImm32(int a, int b)
3137 {
3138     Procedure proc;
3139     BasicBlock* root = proc.addBlock();
3140     root->appendNewControlValue(
3141         proc, Return, Origin(),
3142         root->appendNew<Value>(
3143             proc, BitXor, Origin(),
3144             root->appendNew<Value>(
3145                 proc, Trunc, Origin(),
3146                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3147             root->appendNew<Const32Value>(proc, Origin(), b)));
3148
3149     CHECK(compileAndRun<int>(proc, a) == (a ^ b));
3150 }
3151
3152 void testBitXorImmArg32(int a, int b)
3153 {
3154     Procedure proc;
3155     BasicBlock* root = proc.addBlock();
3156     root->appendNewControlValue(
3157         proc, Return, Origin(),
3158         root->appendNew<Value>(
3159             proc, BitXor, Origin(),
3160             root->appendNew<Const32Value>(proc, Origin(), a),
3161             root->appendNew<Value>(
3162                 proc, Trunc, Origin(),
3163                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3164
3165     CHECK(compileAndRun<int>(proc, b) == (a ^ b));
3166 }
3167
3168 void testBitXorBitXorArgImmImm32(int a, int b, int c)
3169 {
3170     Procedure proc;
3171     BasicBlock* root = proc.addBlock();
3172     Value* innerBitXor = root->appendNew<Value>(
3173         proc, BitXor, Origin(),
3174         root->appendNew<Value>(
3175             proc, Trunc, Origin(),
3176             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3177         root->appendNew<Const32Value>(proc, Origin(), b));
3178     root->appendNewControlValue(
3179         proc, Return, Origin(),
3180         root->appendNew<Value>(
3181             proc, BitXor, Origin(),
3182             innerBitXor,
3183             root->appendNew<Const32Value>(proc, Origin(), c)));
3184
3185     CHECK(compileAndRun<int>(proc, a) == ((a ^ b) ^ c));
3186 }
3187
3188 void testBitXorImmBitXorArgImm32(int a, int b, int c)
3189 {
3190     Procedure proc;
3191     BasicBlock* root = proc.addBlock();
3192     Value* innerBitXor = root->appendNew<Value>(
3193         proc, BitXor, Origin(),
3194         root->appendNew<Value>(
3195             proc, Trunc, Origin(),
3196             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3197         root->appendNew<Const32Value>(proc, Origin(), c));
3198     root->appendNewControlValue(
3199         proc, Return, Origin(),
3200         root->appendNew<Value>(
3201             proc, BitXor, Origin(),
3202             root->appendNew<Const32Value>(proc, Origin(), a),
3203             innerBitXor));
3204
3205     CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c)));
3206 }
3207
3208 void testBitNotArg(int64_t a)
3209 {
3210     Procedure proc;
3211     BasicBlock* root = proc.addBlock();
3212     root->appendNewControlValue(
3213         proc, Return, Origin(),
3214         root->appendNew<Value>(
3215             proc, BitXor, Origin(),
3216             root->appendNew<Const64Value>(proc, Origin(), -1),
3217             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3218
3219     CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3220 }
3221
3222 void testBitNotImm(int64_t a)
3223 {
3224     Procedure proc;
3225     BasicBlock* root = proc.addBlock();
3226     root->appendNewControlValue(
3227         proc, Return, Origin(),
3228         root->appendNew<Value>(
3229             proc, BitXor, Origin(),
3230             root->appendNew<Const64Value>(proc, Origin(), -1),
3231             root->appendNew<Const64Value>(proc, Origin(), a)));
3232
3233     CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3234 }
3235
3236 void testBitNotMem(int64_t a)
3237 {
3238     Procedure proc;
3239     BasicBlock* root = proc.addBlock();
3240     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3241     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
3242     Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
3243         root->appendNew<Const64Value>(proc, Origin(), -1),
3244         load);
3245     root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
3246     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3247
3248     int64_t input = a;
3249     compileAndRun<int32_t>(proc, &input);
3250     CHECK(isIdentical(input, static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3251 }
3252
3253 void testBitNotArg32(int32_t a)
3254 {
3255     Procedure proc;
3256     BasicBlock* root = proc.addBlock();
3257     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
3258         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3259     root->appendNewControlValue(
3260         proc, Return, Origin(),
3261         root->appendNew<Value>(proc, BitXor, Origin(),
3262             root->appendNew<Const32Value>(proc, Origin(), -1),
3263             argument));
3264     CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3265 }
3266
3267 void testBitNotImm32(int32_t a)
3268 {
3269     Procedure proc;
3270     BasicBlock* root = proc.addBlock();
3271     root->appendNewControlValue(
3272         proc, Return, Origin(),
3273         root->appendNew<Value>(
3274             proc, BitXor, Origin(),
3275             root->appendNew<Const32Value>(proc, Origin(), -1),
3276             root->appendNew<Const32Value>(proc, Origin(), a)));
3277
3278     CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3279 }
3280
3281 void testBitNotMem32(int32_t a)
3282 {
3283     Procedure proc;
3284     BasicBlock* root = proc.addBlock();
3285     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3286     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
3287     Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
3288         root->appendNew<Const32Value>(proc, Origin(), -1),
3289         load);
3290     root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
3291     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3292
3293     int32_t input = a;
3294     compileAndRun<int32_t>(proc, &input);
3295     CHECK(isIdentical(input, static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3296 }
3297
3298 void testBitNotOnBooleanAndBranch32(int64_t a, int64_t b)
3299 {
3300     Procedure proc;
3301     BasicBlock* root = proc.addBlock();
3302     BasicBlock* thenCase = proc.addBlock();
3303     BasicBlock* elseCase = proc.addBlock();
3304
3305     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
3306         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3307     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
3308         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3309     Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
3310     Value* argsAreNotEqual = root->appendNew<Value>(proc, BitXor, Origin(),
3311         root->appendNew<Const32Value>(proc, Origin(), -1),
3312         argsAreEqual);
3313
3314     root->appendNewControlValue(
3315         proc, Branch, Origin(),
3316         argsAreNotEqual,
3317         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
3318
3319     thenCase->appendNewControlValue(
3320         proc, Return, Origin(),
3321         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
3322
3323     elseCase->appendNewControlValue(
3324         proc, Return, Origin(),
3325         elseCase->appendNew<Const32Value>(proc, Origin(), -42));
3326
3327     int32_t expectedValue = (a != b) ? 42 : -42;
3328     CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue);
3329 }
3330
3331 void testShlArgs(int64_t a, int64_t b)
3332 {
3333     Procedure proc;
3334     BasicBlock* root = proc.addBlock();
3335     root->appendNewControlValue(
3336         proc, Return, Origin(),
3337         root->appendNew<Value>(
3338             proc, Shl, Origin(),
3339             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3340             root->appendNew<Value>(
3341                 proc, Trunc, Origin(),
3342                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3343
3344     CHECK(compileAndRun<int64_t>(proc, a, b) == (a << b));
3345 }
3346
3347 void testShlImms(int64_t a, int64_t b)
3348 {
3349     Procedure proc;
3350     BasicBlock* root = proc.addBlock();
3351     root->appendNewControlValue(
3352         proc, Return, Origin(),
3353         root->appendNew<Value>(
3354             proc, Shl, Origin(),
3355             root->appendNew<Const64Value>(proc, Origin(), a),
3356             root->appendNew<Const32Value>(proc, Origin(), b)));
3357
3358     CHECK(compileAndRun<int64_t>(proc) == (a << b));
3359 }
3360
3361 void testShlArgImm(int64_t a, int64_t b)
3362 {
3363     Procedure proc;
3364     BasicBlock* root = proc.addBlock();
3365     root->appendNewControlValue(
3366         proc, Return, Origin(),
3367         root->appendNew<Value>(
3368             proc, Shl, Origin(),
3369             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3370             root->appendNew<Const32Value>(proc, Origin(), b)));
3371
3372     CHECK(compileAndRun<int64_t>(proc, a) == (a << b));
3373 }
3374
3375 void testShlArg32(int32_t a)
3376 {
3377     Procedure proc;
3378     BasicBlock* root = proc.addBlock();
3379     Value* value = root->appendNew<Value>(
3380         proc, Trunc, Origin(),
3381         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3382     root->appendNewControlValue(
3383         proc, Return, Origin(),
3384         root->appendNew<Value>(proc, Shl, Origin(), value, value));
3385
3386     CHECK(compileAndRun<int32_t>(proc, a) == (a << a));
3387 }
3388
3389 void testShlArgs32(int32_t a, int32_t b)
3390 {
3391     Procedure proc;
3392     BasicBlock* root = proc.addBlock();
3393     root->appendNewControlValue(
3394         proc, Return, Origin(),
3395         root->appendNew<Value>(
3396             proc, Shl, Origin(),
3397             root->appendNew<Value>(
3398                 proc, Trunc, Origin(),
3399                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3400             root->appendNew<Value>(
3401                 proc, Trunc, Origin(),
3402                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3403
3404     CHECK(compileAndRun<int32_t>(proc, a, b) == (a << b));
3405 }
3406
3407 void testShlImms32(int32_t a, int32_t b)
3408 {
3409     Procedure proc;
3410     BasicBlock* root = proc.addBlock();
3411     root->appendNewControlValue(
3412         proc, Return, Origin(),
3413         root->appendNew<Value>(
3414             proc, Shl, Origin(),
3415             root->appendNew<Const32Value>(proc, Origin(), a),
3416             root->appendNew<Const32Value>(proc, Origin(), b)));
3417
3418     CHECK(compileAndRun<int32_t>(proc) == (a << b));
3419 }
3420
3421 void testShlArgImm32(int32_t a, int32_t b)
3422 {
3423     Procedure proc;
3424     BasicBlock* root = proc.addBlock();
3425     root->appendNewControlValue(
3426         proc, Return, Origin(),
3427         root->appendNew<Value>(
3428             proc, Shl, Origin(),
3429             root->appendNew<Value>(
3430                 proc, Trunc, Origin(),
3431                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3432             root->appendNew<Const32Value>(proc, Origin(), b)));
3433
3434     CHECK(compileAndRun<int32_t>(proc, a) == (a << b));
3435 }
3436
3437 void testSShrArgs(int64_t a, int64_t b)
3438 {
3439     Procedure proc;
3440     BasicBlock* root = proc.addBlock();
3441     root->appendNewControlValue(
3442         proc, Return, Origin(),
3443         root->appendNew<Value>(
3444             proc, SShr, Origin(),
3445             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3446             root->appendNew<Value>(
3447                 proc, Trunc, Origin(),
3448                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3449
3450     CHECK(compileAndRun<int64_t>(proc, a, b) == (a >> b));
3451 }
3452
3453 void testSShrImms(int64_t a, int64_t b)
3454 {
3455     Procedure proc;
3456     BasicBlock* root = proc.addBlock();
3457     root->appendNewControlValue(
3458         proc, Return, Origin(),
3459         root->appendNew<Value>(
3460             proc, SShr, Origin(),
3461             root->appendNew<Const64Value>(proc, Origin(), a),
3462             root->appendNew<Const32Value>(proc, Origin(), b)));
3463
3464     CHECK(compileAndRun<int64_t>(proc) == (a >> b));
3465 }
3466
3467 void testSShrArgImm(int64_t a, int64_t b)
3468 {
3469     Procedure proc;
3470     BasicBlock* root = proc.addBlock();
3471     root->appendNewControlValue(
3472         proc, Return, Origin(),
3473         root->appendNew<Value>(
3474             proc, SShr, Origin(),
3475             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3476             root->appendNew<Const32Value>(proc, Origin(), b)));
3477
3478     CHECK(compileAndRun<int64_t>(proc, a) == (a >> b));
3479 }
3480
3481 void testSShrArg32(int32_t a)
3482 {
3483     Procedure proc;
3484     BasicBlock* root = proc.addBlock();
3485     Value* value = root->appendNew<Value>(
3486         proc, Trunc, Origin(),
3487         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3488     root->appendNewControlValue(
3489         proc, Return, Origin(),
3490         root->appendNew<Value>(proc, SShr, Origin(), value, value));
3491
3492     CHECK(compileAndRun<int32_t>(proc, a) == (a >> (a & 31)));
3493 }
3494
3495 void testSShrArgs32(int32_t a, int32_t b)
3496 {
3497     Procedure proc;
3498     BasicBlock* root = proc.addBlock();
3499     root->appendNewControlValue(
3500         proc, Return, Origin(),
3501         root->appendNew<Value>(
3502             proc, SShr, Origin(),
3503             root->appendNew<Value>(
3504                 proc, Trunc, Origin(),
3505                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3506             root->appendNew<Value>(
3507                 proc, Trunc, Origin(),
3508                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3509
3510     CHECK(compileAndRun<int32_t>(proc, a, b) == (a >> b));
3511 }
3512
3513 void testSShrImms32(int32_t a, int32_t b)
3514 {
3515     Procedure proc;
3516     BasicBlock* root = proc.addBlock();
3517     root->appendNewControlValue(
3518         proc, Return, Origin(),
3519         root->appendNew<Value>(
3520             proc, SShr, Origin(),
3521             root->appendNew<Const32Value>(proc, Origin(), a),
3522             root->appendNew<Const32Value>(proc, Origin(), b)));
3523
3524     CHECK(compileAndRun<int32_t>(proc) == (a >> b));
3525 }
3526
3527 void testSShrArgImm32(int32_t a, int32_t b)
3528 {
3529     Procedure proc;
3530     BasicBlock* root = proc.addBlock();
3531     root->appendNewControlValue(
3532         proc, Return, Origin(),
3533         root->appendNew<Value>(
3534             proc, SShr, Origin(),
3535             root->appendNew<Value>(
3536                 proc, Trunc, Origin(),
3537                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3538             root->appendNew<Const32Value>(proc, Origin(), b)));
3539
3540     CHECK(compileAndRun<int32_t>(proc, a) == (a >> b));
3541 }
3542
3543 void testZShrArgs(uint64_t a, uint64_t b)
3544 {
3545     Procedure proc;
3546     BasicBlock* root = proc.addBlock();
3547     root->appendNewControlValue(
3548         proc, Return, Origin(),
3549         root->appendNew<Value>(
3550             proc, ZShr, Origin(),
3551             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3552             root->appendNew<Value>(
3553                 proc, Trunc, Origin(),
3554                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3555
3556     CHECK(compileAndRun<uint64_t>(proc, a, b) == (a >> b));
3557 }
3558
3559 void testZShrImms(uint64_t a, uint64_t b)
3560 {
3561     Procedure proc;
3562     BasicBlock* root = proc.addBlock();
3563     root->appendNewControlValue(
3564         proc, Return, Origin(),
3565         root->appendNew<Value>(
3566             proc, ZShr, Origin(),
3567             root->appendNew<Const64Value>(proc, Origin(), a),
3568             root->appendNew<Const32Value>(proc, Origin(), b)));
3569
3570     CHECK(compileAndRun<uint64_t>(proc) == (a >> b));
3571 }
3572
3573 void testZShrArgImm(uint64_t a, uint64_t b)
3574 {
3575     Procedure proc;
3576     BasicBlock* root = proc.addBlock();
3577     root->appendNewControlValue(
3578         proc, Return, Origin(),
3579         root->appendNew<Value>(
3580             proc, ZShr, Origin(),
3581             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3582             root->appendNew<Const32Value>(proc, Origin(), b)));
3583
3584     CHECK(compileAndRun<uint64_t>(proc, a) == (a >> b));
3585 }
3586
3587 void testZShrArg32(uint32_t a)
3588 {
3589     Procedure proc;
3590     BasicBlock* root = proc.addBlock();
3591     Value* value = root->appendNew<Value>(
3592         proc, Trunc, Origin(),
3593         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3594     root->appendNewControlValue(
3595         proc, Return, Origin(),
3596         root->appendNew<Value>(proc, ZShr, Origin(), value, value));
3597
3598     CHECK(compileAndRun<uint32_t>(proc, a) == (a >> (a & 31)));
3599 }
3600
3601 void testZShrArgs32(uint32_t a, uint32_t b)
3602 {
3603     Procedure proc;
3604     BasicBlock* root = proc.addBlock();
3605     root->appendNewControlValue(
3606         proc, Return, Origin(),
3607         root->appendNew<Value>(
3608             proc, ZShr, Origin(),
3609             root->appendNew<Value>(
3610                 proc, Trunc, Origin(),
3611                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3612             root->appendNew<Value>(
3613                 proc, Trunc, Origin(),
3614                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3615
3616     CHECK(compileAndRun<uint32_t>(proc, a, b) == (a >> b));
3617 }
3618
3619 void testZShrImms32(uint32_t a, uint32_t b)
3620 {
3621     Procedure proc;
3622     BasicBlock* root = proc.addBlock();
3623     root->appendNewControlValue(
3624         proc, Return, Origin(),
3625         root->appendNew<Value>(
3626             proc, ZShr, Origin(),
3627             root->appendNew<Const32Value>(proc, Origin(), a),
3628             root->appendNew<Const32Value>(proc, Origin(), b)));
3629
3630     CHECK(compileAndRun<uint32_t>(proc) == (a >> b));
3631 }
3632
3633 void testZShrArgImm32(uint32_t a, uint32_t b)
3634 {
3635     Procedure proc;
3636     BasicBlock* root = proc.addBlock();
3637     root->appendNewControlValue(
3638         proc, Return, Origin(),
3639         root->appendNew<Value>(
3640             proc, ZShr, Origin(),
3641             root->appendNew<Value>(
3642                 proc, Trunc, Origin(),
3643                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3644             root->appendNew<Const32Value>(proc, Origin(), b)));
3645
3646     CHECK(compileAndRun<uint32_t>(proc, a) == (a >> b));
3647 }
3648
3649 template<typename IntegerType>
3650 static unsigned countLeadingZero(IntegerType value)
3651 {
3652     unsigned bitCount = sizeof(IntegerType) * 8;
3653     if (!value)
3654         return bitCount;
3655
3656     unsigned counter = 0;
3657     while (!(static_cast<uint64_t>(value) & (1l << (bitCount - 1)))) {
3658         value <<= 1;
3659         ++counter;
3660     }
3661     return counter;
3662 }
3663
3664 void testClzArg64(int64_t a)
3665 {
3666     Procedure proc;
3667     BasicBlock* root = proc.addBlock();
3668     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3669     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
3670     root->appendNewControlValue(proc, Return, Origin(), clzValue);
3671     CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
3672 }
3673
3674 void testClzMem64(int64_t a)
3675 {
3676     Procedure proc;
3677     BasicBlock* root = proc.addBlock();
3678     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3679     MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
3680     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
3681     root->appendNewControlValue(proc, Return, Origin(), clzValue);
3682     CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
3683 }
3684
3685 void testClzArg32(int32_t a)
3686 {
3687     Procedure proc;
3688     BasicBlock* root = proc.addBlock();
3689     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
3690         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3691     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
3692     root->appendNewControlValue(proc, Return, Origin(), clzValue);
3693     CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
3694 }
3695
3696 void testClzMem32(int32_t a)
3697 {
3698     Procedure proc;
3699     BasicBlock* root = proc.addBlock();
3700     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3701     MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
3702     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
3703     root->appendNewControlValue(proc, Return, Origin(), clzValue);
3704     CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
3705 }
3706
3707 void testAbsArg(double a)
3708 {
3709     Procedure proc;
3710     BasicBlock* root = proc.addBlock();
3711     root->appendNewControlValue(
3712         proc, Return, Origin(),
3713         root->appendNew<Value>(
3714             proc, Abs, Origin(),
3715                 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
3716
3717     CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a)));
3718 }
3719
3720 void testAbsImm(double a)
3721 {
3722     Procedure proc;
3723     BasicBlock* root = proc.addBlock();
3724     Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
3725     root->appendNewControlValue(
3726         proc, Return, Origin(),
3727         root->appendNew<Value>(proc, Abs, Origin(), argument));
3728
3729     CHECK(isIdentical(compileAndRun<double>(proc), fabs(a)));
3730 }
3731
3732 void testAbsMem(double a)
3733 {
3734     Procedure proc;
3735     BasicBlock* root = proc.addBlock();
3736     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3737     MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
3738     root->appendNewControlValue(
3739         proc, Return, Origin(),
3740         root->appendNew<Value>(proc, Abs, Origin(), loadDouble));
3741
3742     CHECK(isIdentical(compileAndRun<double>(proc, &a), fabs(a)));
3743 }
3744
3745 void testAbsAbsArg(double a)
3746 {
3747     Procedure proc;
3748     BasicBlock* root = proc.addBlock();
3749     Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(),
3750         root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
3751     Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
3752     root->appendNewControlValue(proc, Return, Origin(), secondAbs);
3753
3754     CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a)));
3755 }
3756
3757 void testAbsBitwiseCastArg(double a)
3758 {
3759     Procedure proc;
3760     BasicBlock* root = proc.addBlock();
3761     Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3762     Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
3763     Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
3764     root->appendNewControlValue(proc, Return, Origin(), absValue);
3765
3766     CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int64_t>(a)), fabs(a)));
3767 }
3768
3769 void testBitwiseCastAbsBitwiseCastArg(double a)
3770 {
3771     Procedure proc;
3772     BasicBlock* root = proc.addBlock();
3773     Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3774     Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
3775     Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
3776     Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
3777
3778     root->appendNewControlValue(proc, Return, Origin(), resultAsInt64);
3779
3780     int64_t expectedResult = bitwise_cast<int64_t>(fabs(a));
3781     CHECK(isIdentical(compileAndRun<int64_t>(proc, bitwise_cast<int64_t>(a)), expectedResult));
3782 }
3783
3784 void testAbsArg(float a)
3785 {
3786     Procedure proc;
3787     BasicBlock* root = proc.addBlock();
3788     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
3789         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3790     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
3791     Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
3792     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
3793     root->appendNewControlValue(proc, Return, Origin(), result32);
3794
3795     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
3796 }
3797
3798 void testAbsImm(float a)
3799 {
3800     Procedure proc;
3801     BasicBlock* root = proc.addBlock();
3802     Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
3803     Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
3804     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
3805     root->appendNewControlValue(proc, Return, Origin(), result32);
3806
3807     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
3808 }
3809
3810 void testAbsMem(float a)
3811 {
3812     Procedure proc;
3813     BasicBlock* root = proc.addBlock();
3814     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3815     MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
3816     Value* result = root->appendNew<Value>(proc, Abs, Origin(), loadFloat);
3817     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
3818     root->appendNewControlValue(proc, Return, Origin(), result32);
3819
3820     CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
3821 }
3822
3823 void testAbsAbsArg(float a)
3824 {
3825     Procedure proc;
3826     BasicBlock* root = proc.addBlock();
3827     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
3828         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3829     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
3830     Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(), argument);
3831     Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
3832     root->appendNewControlValue(proc, Return, Origin(), secondAbs);
3833
3834     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a))));
3835 }
3836
3837 void testAbsBitwiseCastArg(float a)
3838 {
3839     Procedure proc;
3840     BasicBlock* root = proc.addBlock();
3841     Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
3842         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3843     Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
3844     Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
3845     root->appendNewControlValue(proc, Return, Origin(), absValue);
3846
3847     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a))));
3848 }
3849
3850 void testBitwiseCastAbsBitwiseCastArg(float a)
3851 {
3852     Procedure proc;
3853     BasicBlock* root = proc.addBlock();
3854     Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
3855         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3856     Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
3857     Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
3858     Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
3859
3860     root->appendNewControlValue(proc, Return, Origin(), resultAsInt64);
3861
3862     int32_t expectedResult = bitwise_cast<int32_t>(static_cast<float>(fabs(a)));
3863     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), expectedResult));
3864 }
3865
3866 void testAbsArgWithUselessDoubleConversion(float a)
3867 {
3868     Procedure proc;
3869     BasicBlock* root = proc.addBlock();
3870     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
3871         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3872     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
3873     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
3874     Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
3875     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
3876     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
3877     root->appendNewControlValue(proc, Return, Origin(), result32);
3878
3879     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
3880 }
3881
3882 void testAbsArgWithEffectfulDoubleConversion(float a)
3883 {
3884     Procedure proc;
3885     BasicBlock* root = proc.addBlock();
3886     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
3887         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3888     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
3889     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
3890     Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
3891     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
3892     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
3893     Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3894     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
3895     root->appendNewControlValue(proc, Return, Origin(), result32);
3896
3897     double effect = 0;
3898     int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
3899     CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
3900     CHECK(isIdentical(effect, static_cast<double>(fabs(a))));
3901 }
3902
3903 void testCeilArg(double a)
3904 {
3905     Procedure proc;
3906     BasicBlock* root = proc.addBlock();
3907     root->appendNewControlValue(
3908         proc, Return, Origin(),
3909         root->appendNew<Value>(
3910             proc, Ceil, Origin(),
3911                 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
3912
3913     CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
3914 }
3915
3916 void testCeilImm(double a)
3917 {
3918     Procedure proc;
3919     BasicBlock* root = proc.addBlock();
3920     Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
3921     root->appendNewControlValue(
3922         proc, Return, Origin(),
3923         root->appendNew<Value>(proc, Ceil, Origin(), argument));
3924
3925     CHECK(isIdentical(compileAndRun<double>(proc), ceil(a)));
3926 }
3927
3928 void testCeilMem(double a)
3929 {
3930     Procedure proc;
3931     BasicBlock* root = proc.addBlock();
3932     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3933     MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
3934     root->appendNewControlValue(
3935         proc, Return, Origin(),
3936         root->appendNew<Value>(proc, Ceil, Origin(), loadDouble));
3937
3938     CHECK(isIdentical(compileAndRun<double>(proc, &a), ceil(a)));
3939 }
3940
3941 void testCeilCeilArg(double a)
3942 {
3943     Procedure proc;
3944     BasicBlock* root = proc.addBlock();
3945     Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
3946         root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
3947     Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
3948     root->appendNewControlValue(proc, Return, Origin(), secondCeil);
3949
3950     CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
3951 }
3952
3953 void testFloorCeilArg(double a)
3954 {
3955     Procedure proc;
3956     BasicBlock* root = proc.addBlock();
3957     Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
3958         root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
3959     Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil);
3960     root->appendNewControlValue(proc, Return, Origin(), wrappingFloor);
3961
3962     CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
3963 }
3964
3965 void testCeilIToD64(int64_t a)
3966 {
3967     Procedure proc;
3968     BasicBlock* root = proc.addBlock();
3969     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3970     Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
3971
3972     root->appendNewControlValue(
3973         proc, Return, Origin(),
3974         root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
3975
3976     CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
3977 }
3978
3979 void testCeilIToD32(int64_t a)
3980 {
3981     Procedure proc;
3982     BasicBlock* root = proc.addBlock();
3983     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
3984         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3985     Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
3986
3987     root->appendNewControlValue(
3988         proc, Return, Origin(),
3989         root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
3990
3991     CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
3992 }
3993
3994 void testCeilArg(float a)
3995 {
3996     Procedure proc;
3997     BasicBlock* root = proc.addBlock();
3998     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
3999         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4000     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4001     Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4002     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4003     root->appendNewControlValue(proc, Return, Origin(), result32);
4004
4005     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
4006 }
4007
4008 void testCeilImm(float a)
4009 {
4010     Procedure proc;
4011     BasicBlock* root = proc.addBlock();
4012     Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
4013     Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4014     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4015     root->appendNewControlValue(proc, Return, Origin(), result32);
4016
4017     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
4018 }
4019
4020 void testCeilMem(float a)
4021 {
4022     Procedure proc;
4023     BasicBlock* root = proc.addBlock();
4024     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4025     MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
4026     Value* result = root->appendNew<Value>(proc, Ceil, Origin(), loadFloat);
4027     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4028     root->appendNewControlValue(proc, Return, Origin(), result32);
4029
4030     CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(ceilf(a))));
4031 }
4032
4033 void testCeilCeilArg(float a)
4034 {
4035     Procedure proc;
4036     BasicBlock* root = proc.addBlock();
4037     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4038         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4039     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4040     Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4041     Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
4042     root->appendNewControlValue(proc, Return, Origin(), secondCeil);
4043
4044     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
4045 }
4046
4047 void testFloorCeilArg(float a)
4048 {
4049     Procedure proc;
4050     BasicBlock* root = proc.addBlock();
4051     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4052         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4053     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4054     Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4055     Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil);
4056     root->appendNewControlValue(proc, Return, Origin(), wrappingFloor);
4057
4058     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
4059 }
4060
4061 void testCeilArgWithUselessDoubleConversion(float a)
4062 {
4063     Procedure proc;
4064     BasicBlock* root = proc.addBlock();
4065     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4066         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4067     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4068     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
4069     Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
4070     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
4071     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
4072     root->appendNewControlValue(proc, Return, Origin(), result32);
4073
4074     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
4075 }
4076
4077 void testCeilArgWithEffectfulDoubleConversion(float a)
4078 {
4079     Procedure proc;
4080     BasicBlock* root = proc.addBlock();
4081     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4082         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4083     Value* f