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