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