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