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