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