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