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