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