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