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