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