[B3] Typo fix in testb3.cpp
[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 testDivArgFloatWithUselessDoubleConversion(float a)
1031 {
1032     Procedure proc;
1033     BasicBlock* root = proc.addBlock();
1034     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1035         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1036     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1037     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1038     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble, asDouble);
1039     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1040     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1041     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1042
1043     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a)));
1044 }
1045
1046 void testDivArgsFloatWithUselessDoubleConversion(float a, float b)
1047 {
1048     Procedure proc;
1049     BasicBlock* root = proc.addBlock();
1050     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1051         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1052     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1053         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1054     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1055     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1056     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1057     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1058     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1059     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1060     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1061     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1062
1063     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1064 }
1065
1066 void testDivArgsFloatWithEffectfulDoubleConversion(float a, float b)
1067 {
1068     Procedure proc;
1069     BasicBlock* root = proc.addBlock();
1070     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1071         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1072     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1073         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1074     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1075     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1076     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1077     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1078     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1079     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1080     Value* doubleDivress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1081     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleDivress);
1082     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1083     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1084
1085     double effect = 0;
1086     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a / b)));
1087     CHECK(isIdentical(effect, static_cast<double>(a) / static_cast<double>(b)));
1088 }
1089
1090 void testSubArg(int a)
1091 {
1092     Procedure proc;
1093     BasicBlock* root = proc.addBlock();
1094     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1095     root->appendNew<ControlValue>(
1096         proc, Return, Origin(),
1097         root->appendNew<Value>(proc, Sub, Origin(), value, value));
1098
1099     CHECK(!compileAndRun<int>(proc, a));
1100 }
1101
1102 void testSubArgs(int a, int b)
1103 {
1104     Procedure proc;
1105     BasicBlock* root = proc.addBlock();
1106     root->appendNew<ControlValue>(
1107         proc, Return, Origin(),
1108         root->appendNew<Value>(
1109             proc, Sub, Origin(),
1110             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1111             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
1112
1113     CHECK(compileAndRun<int>(proc, a, b) == a - b);
1114 }
1115
1116 void testSubArgImm(int64_t a, int64_t b)
1117 {
1118     Procedure proc;
1119     BasicBlock* root = proc.addBlock();
1120     root->appendNew<ControlValue>(
1121         proc, Return, Origin(),
1122         root->appendNew<Value>(
1123             proc, Sub, Origin(),
1124             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1125             root->appendNew<Const64Value>(proc, Origin(), b)));
1126
1127     CHECK(compileAndRun<int64_t>(proc, a) == a - b);
1128 }
1129
1130 void testNegValueSubOne(int a)
1131 {
1132     Procedure proc;
1133     BasicBlock* root = proc.addBlock();
1134     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1135     Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
1136         root->appendNew<Const64Value>(proc, Origin(), 0),
1137         argument);
1138     Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
1139         negArgument,
1140         root->appendNew<Const64Value>(proc, Origin(), 1));
1141     root->appendNew<ControlValue>(proc, Return, Origin(), negArgumentMinusOne);
1142     CHECK(compileAndRun<int>(proc, a) == -a - 1);
1143 }
1144
1145 void testSubImmArg(int a, int b)
1146 {
1147     Procedure proc;
1148     BasicBlock* root = proc.addBlock();
1149     root->appendNew<ControlValue>(
1150         proc, Return, Origin(),
1151         root->appendNew<Value>(
1152             proc, Sub, Origin(),
1153             root->appendNew<Const64Value>(proc, Origin(), a),
1154             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1155
1156     CHECK(compileAndRun<int>(proc, b) == a - b);
1157 }
1158
1159 void testSubArgMem(int64_t a, int64_t b)
1160 {
1161     Procedure proc;
1162     BasicBlock* root = proc.addBlock();
1163     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1164     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1165     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1166         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1167         load);
1168     root->appendNew<ControlValue>(proc, Return, Origin(), result);
1169
1170     CHECK(compileAndRun<int64_t>(proc, a, &b) == a - b);
1171 }
1172
1173 void testSubMemArg(int64_t a, int64_t b)
1174 {
1175     Procedure proc;
1176     BasicBlock* root = proc.addBlock();
1177     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1178     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1179     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1180         load,
1181         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1182     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1183     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1184
1185     int64_t inputOutput = a;
1186     CHECK(!compileAndRun<int64_t>(proc, &inputOutput, b));
1187     CHECK(inputOutput == a - b);
1188 }
1189
1190 void testSubImmMem(int64_t a, int64_t b)
1191 {
1192     Procedure proc;
1193     BasicBlock* root = proc.addBlock();
1194     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1195     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1196     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1197         root->appendNew<Const64Value>(proc, Origin(), a),
1198         load);
1199     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1200     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1201
1202     int64_t inputOutput = b;
1203     CHECK(!compileAndRun<int>(proc, &inputOutput));
1204     CHECK(inputOutput == a - b);
1205 }
1206
1207 void testSubMemImm(int64_t a, int64_t b)
1208 {
1209     Procedure proc;
1210     BasicBlock* root = proc.addBlock();
1211     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1212     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1213     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1214         load,
1215         root->appendNew<Const64Value>(proc, Origin(), b));
1216     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1217     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1218
1219     int64_t inputOutput = a;
1220     CHECK(!compileAndRun<int>(proc, &inputOutput));
1221     CHECK(inputOutput == a - b);
1222 }
1223
1224
1225 void testSubArgs32(int a, int b)
1226 {
1227     Procedure proc;
1228     BasicBlock* root = proc.addBlock();
1229     root->appendNew<ControlValue>(
1230         proc, Return, Origin(),
1231         root->appendNew<Value>(
1232             proc, Sub, Origin(),
1233             root->appendNew<Value>(
1234                 proc, Trunc, Origin(),
1235                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1236             root->appendNew<Value>(
1237                 proc, Trunc, Origin(),
1238                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1239
1240     CHECK(compileAndRun<int>(proc, a, b) == a - b);
1241 }
1242
1243 void testSubArgImm32(int a, int b)
1244 {
1245     Procedure proc;
1246     BasicBlock* root = proc.addBlock();
1247     root->appendNew<ControlValue>(
1248         proc, Return, Origin(),
1249         root->appendNew<Value>(
1250             proc, Sub, Origin(),
1251             root->appendNew<Value>(
1252                 proc, Trunc, Origin(),
1253                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1254             root->appendNew<Const32Value>(proc, Origin(), b)));
1255
1256     CHECK(compileAndRun<int>(proc, a) == a - b);
1257 }
1258
1259 void testSubImmArg32(int a, int b)
1260 {
1261     Procedure proc;
1262     BasicBlock* root = proc.addBlock();
1263     root->appendNew<ControlValue>(
1264         proc, Return, Origin(),
1265         root->appendNew<Value>(
1266             proc, Sub, Origin(),
1267             root->appendNew<Const32Value>(proc, Origin(), a),
1268             root->appendNew<Value>(
1269                 proc, Trunc, Origin(),
1270                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
1271
1272     CHECK(compileAndRun<int>(proc, b) == a - b);
1273 }
1274
1275 void testSubMemArg32(int32_t a, int32_t b)
1276 {
1277     Procedure proc;
1278     BasicBlock* root = proc.addBlock();
1279     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1280     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
1281     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
1282         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1283     Value* result = root->appendNew<Value>(proc, Sub, Origin(), load, argument);
1284     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1285     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1286
1287     int32_t inputOutput = a;
1288     CHECK(!compileAndRun<int32_t>(proc, &inputOutput, b));
1289     CHECK(inputOutput == a - b);
1290 }
1291
1292 void testSubArgMem32(int32_t a, int32_t b)
1293 {
1294     Procedure proc;
1295     BasicBlock* root = proc.addBlock();
1296     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1297     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
1298     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
1299         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1300     Value* result = root->appendNew<Value>(proc, Sub, Origin(), argument, load);
1301     root->appendNew<ControlValue>(proc, Return, Origin(), result);
1302
1303     CHECK(compileAndRun<int32_t>(proc, a, &b) == a - b);
1304 }
1305
1306 void testSubImmMem32(int32_t a, int32_t b)
1307 {
1308     Procedure proc;
1309     BasicBlock* root = proc.addBlock();
1310     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1311     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
1312     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1313         root->appendNew<Const32Value>(proc, Origin(), a),
1314         load);
1315     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1316     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1317
1318     int32_t inputOutput = b;
1319     CHECK(!compileAndRun<int>(proc, &inputOutput));
1320     CHECK(inputOutput == a - b);
1321 }
1322
1323 void testSubMemImm32(int32_t a, int32_t b)
1324 {
1325     Procedure proc;
1326     BasicBlock* root = proc.addBlock();
1327     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1328     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
1329     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1330         load,
1331         root->appendNew<Const32Value>(proc, Origin(), b));
1332     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1333     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1334
1335     int32_t inputOutput = a;
1336     CHECK(!compileAndRun<int>(proc, &inputOutput));
1337     CHECK(inputOutput == a - b);
1338 }
1339
1340 void testNegValueSubOne32(int a)
1341 {
1342     Procedure proc;
1343     BasicBlock* root = proc.addBlock();
1344     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
1345         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1346     Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
1347         root->appendNew<Const32Value>(proc, Origin(), 0),
1348         argument);
1349     Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
1350         negArgument,
1351         root->appendNew<Const32Value>(proc, Origin(), 1));
1352     root->appendNew<ControlValue>(proc, Return, Origin(), negArgumentMinusOne);
1353     CHECK(compileAndRun<int>(proc, a) == -a - 1);
1354 }
1355
1356 void testSubArgDouble(double a)
1357 {
1358     Procedure proc;
1359     BasicBlock* root = proc.addBlock();
1360     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1361     root->appendNew<ControlValue>(
1362         proc, Return, Origin(),
1363         root->appendNew<Value>(proc, Sub, Origin(), value, value));
1364
1365     CHECK(isIdentical(compileAndRun<double>(proc, a), a - a));
1366 }
1367
1368 void testSubArgsDouble(double a, double b)
1369 {
1370     Procedure proc;
1371     BasicBlock* root = proc.addBlock();
1372     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1373     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1374     root->appendNew<ControlValue>(
1375         proc, Return, Origin(),
1376         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
1377
1378     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a - b));
1379 }
1380
1381 void testSubArgImmDouble(double a, double b)
1382 {
1383     Procedure proc;
1384     BasicBlock* root = proc.addBlock();
1385     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1386     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1387     root->appendNew<ControlValue>(
1388         proc, Return, Origin(),
1389         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
1390
1391     CHECK(isIdentical(compileAndRun<double>(proc, a), a - b));
1392 }
1393
1394 void testSubImmArgDouble(double a, double b)
1395 {
1396     Procedure proc;
1397     BasicBlock* root = proc.addBlock();
1398     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1399     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1400     root->appendNew<ControlValue>(
1401         proc, Return, Origin(),
1402         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
1403
1404     CHECK(isIdentical(compileAndRun<double>(proc, b), a - b));
1405 }
1406
1407 void testSubImmsDouble(double a, double b)
1408 {
1409     Procedure proc;
1410     BasicBlock* root = proc.addBlock();
1411     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1412     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1413     root->appendNew<ControlValue>(
1414         proc, Return, Origin(),
1415         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
1416     
1417     CHECK(isIdentical(compileAndRun<double>(proc), a - b));
1418 }
1419
1420 void testSubArgFloat(float a)
1421 {
1422     Procedure proc;
1423     BasicBlock* root = proc.addBlock();
1424     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1425         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1426     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1427     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, floatValue);
1428     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1429     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1430
1431
1432     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
1433 }
1434
1435 void testSubArgsFloat(float a, float b)
1436 {
1437     Procedure proc;
1438     BasicBlock* root = proc.addBlock();
1439     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1440         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1441     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1442         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1443     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1444     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1445     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue1, floatValue2);
1446     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1447     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1448
1449     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
1450 }
1451
1452 void testSubArgImmFloat(float a, float b)
1453 {
1454     Procedure proc;
1455     BasicBlock* root = proc.addBlock();
1456     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1457         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1458     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1459     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1460     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, constValue);
1461     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1462     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1463
1464     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - b)));
1465 }
1466
1467 void testSubImmArgFloat(float a, float b)
1468 {
1469     Procedure proc;
1470     BasicBlock* root = proc.addBlock();
1471     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1472         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1473     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1474     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1475     Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue, floatValue);
1476     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1477     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1478
1479     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
1480 }
1481
1482 void testSubImmsFloat(float a, float b)
1483 {
1484     Procedure proc;
1485     BasicBlock* root = proc.addBlock();
1486     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1487     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1488     Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue1, constValue2);
1489     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1490     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1491
1492     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a - b)));
1493 }
1494
1495 void testSubArgFloatWithUselessDoubleConversion(float a)
1496 {
1497     Procedure proc;
1498     BasicBlock* root = proc.addBlock();
1499     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1500         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1501     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1502     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1503     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble, asDouble);
1504     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1505     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1506     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1507
1508     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
1509 }
1510
1511 void testSubArgsFloatWithUselessDoubleConversion(float a, float b)
1512 {
1513     Procedure proc;
1514     BasicBlock* root = proc.addBlock();
1515     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1516         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1517     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1518         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1519     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1520     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1521     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1522     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1523     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
1524     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1525     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1526     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1527
1528     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
1529 }
1530
1531 void testSubArgsFloatWithEffectfulDoubleConversion(float a, float b)
1532 {
1533     Procedure proc;
1534     BasicBlock* root = proc.addBlock();
1535     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1536         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1537     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1538         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1539     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1540     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1541     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1542     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1543     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
1544     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1545     Value* doubleSubress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1546     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleSubress);
1547     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1548     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
1549
1550     double effect = 0;
1551     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a - b)));
1552     CHECK(isIdentical(effect, static_cast<double>(a) - static_cast<double>(b)));
1553 }
1554
1555 void testBitAndArgs(int64_t a, int64_t b)
1556 {
1557     Procedure proc;
1558     BasicBlock* root = proc.addBlock();
1559     root->appendNew<ControlValue>(
1560         proc, Return, Origin(),
1561         root->appendNew<Value>(
1562             proc, BitAnd, Origin(),
1563             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1564             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
1565
1566     CHECK(compileAndRun<int64_t>(proc, a, b) == (a & b));
1567 }
1568
1569 void testBitAndSameArg(int64_t a)
1570 {
1571     Procedure proc;
1572     BasicBlock* root = proc.addBlock();
1573     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1574     root->appendNew<ControlValue>(
1575         proc, Return, Origin(),
1576         root->appendNew<Value>(
1577             proc, BitAnd, Origin(),
1578             argument,
1579             argument));
1580
1581     CHECK(compileAndRun<int64_t>(proc, a) == a);
1582 }
1583
1584 void testBitAndImms(int64_t a, int64_t b)
1585 {
1586     Procedure proc;
1587     BasicBlock* root = proc.addBlock();
1588     root->appendNew<ControlValue>(
1589         proc, Return, Origin(),
1590         root->appendNew<Value>(
1591             proc, BitAnd, Origin(),
1592             root->appendNew<Const64Value>(proc, Origin(), a),
1593             root->appendNew<Const64Value>(proc, Origin(), b)));
1594
1595     CHECK(compileAndRun<int64_t>(proc) == (a & b));
1596 }
1597
1598 void testBitAndArgImm(int64_t a, int64_t b)
1599 {
1600     Procedure proc;
1601     BasicBlock* root = proc.addBlock();
1602     root->appendNew<ControlValue>(
1603         proc, Return, Origin(),
1604         root->appendNew<Value>(
1605             proc, BitAnd, Origin(),
1606             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1607             root->appendNew<Const64Value>(proc, Origin(), b)));
1608
1609     CHECK(compileAndRun<int64_t>(proc, a) == (a & b));
1610 }
1611
1612 void testBitAndImmArg(int64_t a, int64_t b)
1613 {
1614     Procedure proc;
1615     BasicBlock* root = proc.addBlock();
1616     root->appendNew<ControlValue>(
1617         proc, Return, Origin(),
1618         root->appendNew<Value>(
1619             proc, BitAnd, Origin(),
1620             root->appendNew<Const64Value>(proc, Origin(), a),
1621             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1622
1623     CHECK(compileAndRun<int64_t>(proc, b) == (a & b));
1624 }
1625
1626 void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c)
1627 {
1628     Procedure proc;
1629     BasicBlock* root = proc.addBlock();
1630     Value* innerBitAnd = root->appendNew<Value>(
1631         proc, BitAnd, Origin(),
1632         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1633         root->appendNew<Const64Value>(proc, Origin(), b));
1634     root->appendNew<ControlValue>(
1635         proc, Return, Origin(),
1636         root->appendNew<Value>(
1637             proc, BitAnd, Origin(),
1638             innerBitAnd,
1639             root->appendNew<Const64Value>(proc, Origin(), c)));
1640
1641     CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c));
1642 }
1643
1644 void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c)
1645 {
1646     Procedure proc;
1647     BasicBlock* root = proc.addBlock();
1648     Value* innerBitAnd = root->appendNew<Value>(
1649         proc, BitAnd, Origin(),
1650         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1651         root->appendNew<Const64Value>(proc, Origin(), c));
1652     root->appendNew<ControlValue>(
1653         proc, Return, Origin(),
1654         root->appendNew<Value>(
1655             proc, BitAnd, Origin(),
1656             root->appendNew<Const64Value>(proc, Origin(), a),
1657             innerBitAnd));
1658
1659     CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c)));
1660 }
1661
1662 void testBitAndArgs32(int a, int b)
1663 {
1664     Procedure proc;
1665     BasicBlock* root = proc.addBlock();
1666     root->appendNew<ControlValue>(
1667         proc, Return, Origin(),
1668         root->appendNew<Value>(
1669             proc, BitAnd, Origin(),
1670             root->appendNew<Value>(
1671                 proc, Trunc, Origin(),
1672                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1673             root->appendNew<Value>(
1674                 proc, Trunc, Origin(),
1675                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1676
1677     CHECK(compileAndRun<int>(proc, a, b) == (a & b));
1678 }
1679
1680 void testBitAndSameArg32(int a)
1681 {
1682     Procedure proc;
1683     BasicBlock* root = proc.addBlock();
1684     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
1685         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1686     root->appendNew<ControlValue>(
1687         proc, Return, Origin(),
1688         root->appendNew<Value>(
1689             proc, BitAnd, Origin(),
1690             argument,
1691             argument));
1692
1693     CHECK(compileAndRun<int>(proc, a) == a);
1694 }
1695
1696 void testBitAndImms32(int a, int b)
1697 {
1698     Procedure proc;
1699     BasicBlock* root = proc.addBlock();
1700     root->appendNew<ControlValue>(
1701         proc, Return, Origin(),
1702         root->appendNew<Value>(
1703             proc, BitAnd, Origin(),
1704             root->appendNew<Const32Value>(proc, Origin(), a),
1705             root->appendNew<Const32Value>(proc, Origin(), b)));
1706
1707     CHECK(compileAndRun<int>(proc) == (a & b));
1708 }
1709
1710 void testBitAndArgImm32(int a, int b)
1711 {
1712     Procedure proc;
1713     BasicBlock* root = proc.addBlock();
1714     root->appendNew<ControlValue>(
1715         proc, Return, Origin(),
1716         root->appendNew<Value>(
1717             proc, BitAnd, Origin(),
1718             root->appendNew<Value>(
1719                 proc, Trunc, Origin(),
1720                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1721             root->appendNew<Const32Value>(proc, Origin(), b)));
1722
1723     CHECK(compileAndRun<int>(proc, a) == (a & b));
1724 }
1725
1726 void testBitAndImmArg32(int a, int b)
1727 {
1728     Procedure proc;
1729     BasicBlock* root = proc.addBlock();
1730     root->appendNew<ControlValue>(
1731         proc, Return, Origin(),
1732         root->appendNew<Value>(
1733             proc, BitAnd, Origin(),
1734             root->appendNew<Const32Value>(proc, Origin(), a),
1735             root->appendNew<Value>(
1736                 proc, Trunc, Origin(),
1737                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
1738
1739     CHECK(compileAndRun<int>(proc, b) == (a & b));
1740 }
1741
1742 void testBitAndBitAndArgImmImm32(int a, int b, int c)
1743 {
1744     Procedure proc;
1745     BasicBlock* root = proc.addBlock();
1746     Value* innerBitAnd = root->appendNew<Value>(
1747         proc, BitAnd, Origin(),
1748         root->appendNew<Value>(
1749             proc, Trunc, Origin(),
1750             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1751         root->appendNew<Const32Value>(proc, Origin(), b));
1752     root->appendNew<ControlValue>(
1753         proc, Return, Origin(),
1754         root->appendNew<Value>(
1755             proc, BitAnd, Origin(),
1756             innerBitAnd,
1757             root->appendNew<Const32Value>(proc, Origin(), c)));
1758
1759     CHECK(compileAndRun<int>(proc, a) == ((a & b) & c));
1760 }
1761
1762 void testBitAndImmBitAndArgImm32(int a, int b, int c)
1763 {
1764     Procedure proc;
1765     BasicBlock* root = proc.addBlock();
1766     Value* innerBitAnd = root->appendNew<Value>(
1767         proc, BitAnd, Origin(),
1768         root->appendNew<Value>(
1769             proc, Trunc, Origin(),
1770             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1771         root->appendNew<Const32Value>(proc, Origin(), c));
1772     root->appendNew<ControlValue>(
1773         proc, Return, Origin(),
1774         root->appendNew<Value>(
1775             proc, BitAnd, Origin(),
1776             root->appendNew<Const32Value>(proc, Origin(), a),
1777             innerBitAnd));
1778
1779     CHECK(compileAndRun<int>(proc, b) == (a & (b & c)));
1780 }
1781
1782 void testBitAndWithMaskReturnsBooleans(int64_t a, int64_t b)
1783 {
1784     Procedure proc;
1785     BasicBlock* root = proc.addBlock();
1786     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1787     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1788     Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg0, arg1);
1789     Value* maskedEqual = root->appendNew<Value>(proc, BitAnd, Origin(),
1790         root->appendNew<Const32Value>(proc, Origin(), 0x5),
1791         equal);
1792     Value* inverted = root->appendNew<Value>(proc, BitXor, Origin(),
1793         root->appendNew<Const32Value>(proc, Origin(), 0x1),
1794         maskedEqual);
1795     Value* select = root->appendNew<Value>(proc, Select, Origin(), inverted,
1796         root->appendNew<Const64Value>(proc, Origin(), 42),
1797         root->appendNew<Const64Value>(proc, Origin(), -5));
1798
1799     root->appendNew<ControlValue>(proc, Return, Origin(), select);
1800
1801     int64_t expected = (a == b) ? -5 : 42;
1802     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
1803 }
1804
1805 void testBitOrArgs(int64_t a, int64_t b)
1806 {
1807     Procedure proc;
1808     BasicBlock* root = proc.addBlock();
1809     root->appendNew<ControlValue>(
1810         proc, Return, Origin(),
1811         root->appendNew<Value>(
1812             proc, BitOr, Origin(),
1813             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1814             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
1815
1816     CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b));
1817 }
1818
1819 void testBitOrSameArg(int64_t a)
1820 {
1821     Procedure proc;
1822     BasicBlock* root = proc.addBlock();
1823     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1824     root->appendNew<ControlValue>(
1825         proc, Return, Origin(),
1826         root->appendNew<Value>(
1827             proc, BitOr, Origin(),
1828             argument,
1829             argument));
1830
1831     CHECK(compileAndRun<int64_t>(proc, a) == a);
1832 }
1833
1834 void testBitOrImms(int64_t a, int64_t b)
1835 {
1836     Procedure proc;
1837     BasicBlock* root = proc.addBlock();
1838     root->appendNew<ControlValue>(
1839         proc, Return, Origin(),
1840         root->appendNew<Value>(
1841             proc, BitOr, Origin(),
1842             root->appendNew<Const64Value>(proc, Origin(), a),
1843             root->appendNew<Const64Value>(proc, Origin(), b)));
1844
1845     CHECK(compileAndRun<int64_t>(proc) == (a | b));
1846 }
1847
1848 void testBitOrArgImm(int64_t a, int64_t b)
1849 {
1850     Procedure proc;
1851     BasicBlock* root = proc.addBlock();
1852     root->appendNew<ControlValue>(
1853         proc, Return, Origin(),
1854         root->appendNew<Value>(
1855             proc, BitOr, Origin(),
1856             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1857             root->appendNew<Const64Value>(proc, Origin(), b)));
1858
1859     CHECK(compileAndRun<int64_t>(proc, a) == (a | b));
1860 }
1861
1862 void testBitOrImmArg(int64_t a, int64_t b)
1863 {
1864     Procedure proc;
1865     BasicBlock* root = proc.addBlock();
1866     root->appendNew<ControlValue>(
1867         proc, Return, Origin(),
1868         root->appendNew<Value>(
1869             proc, BitOr, Origin(),
1870             root->appendNew<Const64Value>(proc, Origin(), a),
1871             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1872
1873     CHECK(compileAndRun<int64_t>(proc, b) == (a | b));
1874 }
1875
1876 void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c)
1877 {
1878     Procedure proc;
1879     BasicBlock* root = proc.addBlock();
1880     Value* innerBitOr = root->appendNew<Value>(
1881         proc, BitOr, Origin(),
1882         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1883         root->appendNew<Const64Value>(proc, Origin(), b));
1884     root->appendNew<ControlValue>(
1885         proc, Return, Origin(),
1886         root->appendNew<Value>(
1887             proc, BitOr, Origin(),
1888             innerBitOr,
1889             root->appendNew<Const64Value>(proc, Origin(), c)));
1890
1891     CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c));
1892 }
1893
1894 void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c)
1895 {
1896     Procedure proc;
1897     BasicBlock* root = proc.addBlock();
1898     Value* innerBitOr = root->appendNew<Value>(
1899         proc, BitOr, Origin(),
1900         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1901         root->appendNew<Const64Value>(proc, Origin(), c));
1902     root->appendNew<ControlValue>(
1903         proc, Return, Origin(),
1904         root->appendNew<Value>(
1905             proc, BitOr, Origin(),
1906             root->appendNew<Const64Value>(proc, Origin(), a),
1907             innerBitOr));
1908
1909     CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c)));
1910 }
1911
1912 void testBitOrArgs32(int a, int b)
1913 {
1914     Procedure proc;
1915     BasicBlock* root = proc.addBlock();
1916     root->appendNew<ControlValue>(
1917         proc, Return, Origin(),
1918         root->appendNew<Value>(
1919             proc, BitOr, Origin(),
1920             root->appendNew<Value>(
1921                 proc, Trunc, Origin(),
1922                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1923             root->appendNew<Value>(
1924                 proc, Trunc, Origin(),
1925                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1926
1927     CHECK(compileAndRun<int>(proc, a, b) == (a | b));
1928 }
1929
1930 void testBitOrSameArg32(int a)
1931 {
1932     Procedure proc;
1933     BasicBlock* root = proc.addBlock();
1934     Value* argument = root->appendNew<Value>(
1935         proc, Trunc, Origin(),
1936             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1937     root->appendNew<ControlValue>(
1938         proc, Return, Origin(),
1939         root->appendNew<Value>(
1940             proc, BitOr, Origin(),
1941             argument,
1942             argument));
1943
1944     CHECK(compileAndRun<int>(proc, a) == a);
1945 }
1946
1947 void testBitOrImms32(int a, int b)
1948 {
1949     Procedure proc;
1950     BasicBlock* root = proc.addBlock();
1951     root->appendNew<ControlValue>(
1952         proc, Return, Origin(),
1953         root->appendNew<Value>(
1954             proc, BitOr, Origin(),
1955             root->appendNew<Const32Value>(proc, Origin(), a),
1956             root->appendNew<Const32Value>(proc, Origin(), b)));
1957
1958     CHECK(compileAndRun<int>(proc) == (a | b));
1959 }
1960
1961 void testBitOrArgImm32(int a, int b)
1962 {
1963     Procedure proc;
1964     BasicBlock* root = proc.addBlock();
1965     root->appendNew<ControlValue>(
1966         proc, Return, Origin(),
1967         root->appendNew<Value>(
1968             proc, BitOr, Origin(),
1969             root->appendNew<Value>(
1970                 proc, Trunc, Origin(),
1971                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1972             root->appendNew<Const32Value>(proc, Origin(), b)));
1973
1974     CHECK(compileAndRun<int>(proc, a) == (a | b));
1975 }
1976
1977 void testBitOrImmArg32(int a, int b)
1978 {
1979     Procedure proc;
1980     BasicBlock* root = proc.addBlock();
1981     root->appendNew<ControlValue>(
1982         proc, Return, Origin(),
1983         root->appendNew<Value>(
1984             proc, BitOr, Origin(),
1985             root->appendNew<Const32Value>(proc, Origin(), a),
1986             root->appendNew<Value>(
1987                 proc, Trunc, Origin(),
1988                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
1989
1990     CHECK(compileAndRun<int>(proc, b) == (a | b));
1991 }
1992
1993 void testBitOrBitOrArgImmImm32(int a, int b, int c)
1994 {
1995     Procedure proc;
1996     BasicBlock* root = proc.addBlock();
1997     Value* innerBitOr = root->appendNew<Value>(
1998         proc, BitOr, Origin(),
1999         root->appendNew<Value>(
2000             proc, Trunc, Origin(),
2001             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2002         root->appendNew<Const32Value>(proc, Origin(), b));
2003     root->appendNew<ControlValue>(
2004         proc, Return, Origin(),
2005         root->appendNew<Value>(
2006             proc, BitOr, Origin(),
2007             innerBitOr,
2008             root->appendNew<Const32Value>(proc, Origin(), c)));
2009
2010     CHECK(compileAndRun<int>(proc, a) == ((a | b) | c));
2011 }
2012
2013 void testBitOrImmBitOrArgImm32(int a, int b, int c)
2014 {
2015     Procedure proc;
2016     BasicBlock* root = proc.addBlock();
2017     Value* innerBitOr = root->appendNew<Value>(
2018         proc, BitOr, Origin(),
2019         root->appendNew<Value>(
2020             proc, Trunc, Origin(),
2021             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2022         root->appendNew<Const32Value>(proc, Origin(), c));
2023     root->appendNew<ControlValue>(
2024         proc, Return, Origin(),
2025         root->appendNew<Value>(
2026             proc, BitOr, Origin(),
2027             root->appendNew<Const32Value>(proc, Origin(), a),
2028             innerBitOr));
2029
2030     CHECK(compileAndRun<int>(proc, b) == (a | (b | c)));
2031 }
2032
2033 void testBitXorArgs(int64_t a, int64_t b)
2034 {
2035     Procedure proc;
2036     BasicBlock* root = proc.addBlock();
2037     root->appendNew<ControlValue>(
2038         proc, Return, Origin(),
2039         root->appendNew<Value>(
2040             proc, BitXor, Origin(),
2041             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2042             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2043
2044     CHECK(compileAndRun<int64_t>(proc, a, b) == (a ^ b));
2045 }
2046
2047 void testBitXorSameArg(int64_t a)
2048 {
2049     Procedure proc;
2050     BasicBlock* root = proc.addBlock();
2051     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2052     root->appendNew<ControlValue>(
2053         proc, Return, Origin(),
2054         root->appendNew<Value>(
2055             proc, BitXor, Origin(),
2056             argument,
2057             argument));
2058
2059     CHECK(!compileAndRun<int64_t>(proc, a));
2060 }
2061
2062 void testBitXorImms(int64_t a, int64_t b)
2063 {
2064     Procedure proc;
2065     BasicBlock* root = proc.addBlock();
2066     root->appendNew<ControlValue>(
2067         proc, Return, Origin(),
2068         root->appendNew<Value>(
2069             proc, BitXor, Origin(),
2070             root->appendNew<Const64Value>(proc, Origin(), a),
2071             root->appendNew<Const64Value>(proc, Origin(), b)));
2072
2073     CHECK(compileAndRun<int64_t>(proc) == (a ^ b));
2074 }
2075
2076 void testBitXorArgImm(int64_t a, int64_t b)
2077 {
2078     Procedure proc;
2079     BasicBlock* root = proc.addBlock();
2080     root->appendNew<ControlValue>(
2081         proc, Return, Origin(),
2082         root->appendNew<Value>(
2083             proc, BitXor, Origin(),
2084             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2085             root->appendNew<Const64Value>(proc, Origin(), b)));
2086
2087     CHECK(compileAndRun<int64_t>(proc, a) == (a ^ b));
2088 }
2089
2090 void testBitXorImmArg(int64_t a, int64_t b)
2091 {
2092     Procedure proc;
2093     BasicBlock* root = proc.addBlock();
2094     root->appendNew<ControlValue>(
2095         proc, Return, Origin(),
2096         root->appendNew<Value>(
2097             proc, BitXor, Origin(),
2098             root->appendNew<Const64Value>(proc, Origin(), a),
2099             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2100
2101     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ b));
2102 }
2103
2104 void testBitXorBitXorArgImmImm(int64_t a, int64_t b, int64_t c)
2105 {
2106     Procedure proc;
2107     BasicBlock* root = proc.addBlock();
2108     Value* innerBitXor = root->appendNew<Value>(
2109         proc, BitXor, Origin(),
2110         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2111         root->appendNew<Const64Value>(proc, Origin(), b));
2112     root->appendNew<ControlValue>(
2113         proc, Return, Origin(),
2114         root->appendNew<Value>(
2115             proc, BitXor, Origin(),
2116             innerBitXor,
2117             root->appendNew<Const64Value>(proc, Origin(), c)));
2118
2119     CHECK(compileAndRun<int64_t>(proc, a) == ((a ^ b) ^ c));
2120 }
2121
2122 void testBitXorImmBitXorArgImm(int64_t a, int64_t b, int64_t c)
2123 {
2124     Procedure proc;
2125     BasicBlock* root = proc.addBlock();
2126     Value* innerBitXor = root->appendNew<Value>(
2127         proc, BitXor, Origin(),
2128         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2129         root->appendNew<Const64Value>(proc, Origin(), c));
2130     root->appendNew<ControlValue>(
2131         proc, Return, Origin(),
2132         root->appendNew<Value>(
2133             proc, BitXor, Origin(),
2134             root->appendNew<Const64Value>(proc, Origin(), a),
2135             innerBitXor));
2136
2137     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ (b ^ c)));
2138 }
2139
2140 void testBitXorArgs32(int a, int b)
2141 {
2142     Procedure proc;
2143     BasicBlock* root = proc.addBlock();
2144     root->appendNew<ControlValue>(
2145         proc, Return, Origin(),
2146         root->appendNew<Value>(
2147             proc, BitXor, Origin(),
2148             root->appendNew<Value>(
2149                 proc, Trunc, Origin(),
2150                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2151             root->appendNew<Value>(
2152                 proc, Trunc, Origin(),
2153                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2154
2155     CHECK(compileAndRun<int>(proc, a, b) == (a ^ b));
2156 }
2157
2158 void testBitXorSameArg32(int a)
2159 {
2160     Procedure proc;
2161     BasicBlock* root = proc.addBlock();
2162     Value* argument = root->appendNew<Value>(
2163         proc, Trunc, Origin(),
2164             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2165     root->appendNew<ControlValue>(
2166         proc, Return, Origin(),
2167         root->appendNew<Value>(
2168             proc, BitXor, Origin(),
2169             argument,
2170             argument));
2171
2172     CHECK(!compileAndRun<int>(proc, a));
2173 }
2174
2175 void testBitXorImms32(int a, int b)
2176 {
2177     Procedure proc;
2178     BasicBlock* root = proc.addBlock();
2179     root->appendNew<ControlValue>(
2180         proc, Return, Origin(),
2181         root->appendNew<Value>(
2182             proc, BitXor, Origin(),
2183             root->appendNew<Const32Value>(proc, Origin(), a),
2184             root->appendNew<Const32Value>(proc, Origin(), b)));
2185
2186     CHECK(compileAndRun<int>(proc) == (a ^ b));
2187 }
2188
2189 void testBitXorArgImm32(int a, int b)
2190 {
2191     Procedure proc;
2192     BasicBlock* root = proc.addBlock();
2193     root->appendNew<ControlValue>(
2194         proc, Return, Origin(),
2195         root->appendNew<Value>(
2196             proc, BitXor, Origin(),
2197             root->appendNew<Value>(
2198                 proc, Trunc, Origin(),
2199                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2200             root->appendNew<Const32Value>(proc, Origin(), b)));
2201
2202     CHECK(compileAndRun<int>(proc, a) == (a ^ b));
2203 }
2204
2205 void testBitXorImmArg32(int a, int b)
2206 {
2207     Procedure proc;
2208     BasicBlock* root = proc.addBlock();
2209     root->appendNew<ControlValue>(
2210         proc, Return, Origin(),
2211         root->appendNew<Value>(
2212             proc, BitXor, Origin(),
2213             root->appendNew<Const32Value>(proc, Origin(), a),
2214             root->appendNew<Value>(
2215                 proc, Trunc, Origin(),
2216                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2217
2218     CHECK(compileAndRun<int>(proc, b) == (a ^ b));
2219 }
2220
2221 void testBitXorBitXorArgImmImm32(int a, int b, int c)
2222 {
2223     Procedure proc;
2224     BasicBlock* root = proc.addBlock();
2225     Value* innerBitXor = root->appendNew<Value>(
2226         proc, BitXor, Origin(),
2227         root->appendNew<Value>(
2228             proc, Trunc, Origin(),
2229             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2230         root->appendNew<Const32Value>(proc, Origin(), b));
2231     root->appendNew<ControlValue>(
2232         proc, Return, Origin(),
2233         root->appendNew<Value>(
2234             proc, BitXor, Origin(),
2235             innerBitXor,
2236             root->appendNew<Const32Value>(proc, Origin(), c)));
2237
2238     CHECK(compileAndRun<int>(proc, a) == ((a ^ b) ^ c));
2239 }
2240
2241 void testBitXorImmBitXorArgImm32(int a, int b, int c)
2242 {
2243     Procedure proc;
2244     BasicBlock* root = proc.addBlock();
2245     Value* innerBitXor = root->appendNew<Value>(
2246         proc, BitXor, Origin(),
2247         root->appendNew<Value>(
2248             proc, Trunc, Origin(),
2249             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2250         root->appendNew<Const32Value>(proc, Origin(), c));
2251     root->appendNew<ControlValue>(
2252         proc, Return, Origin(),
2253         root->appendNew<Value>(
2254             proc, BitXor, Origin(),
2255             root->appendNew<Const32Value>(proc, Origin(), a),
2256             innerBitXor));
2257
2258     CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c)));
2259 }
2260
2261 void testBitNotArg(int64_t a)
2262 {
2263     Procedure proc;
2264     BasicBlock* root = proc.addBlock();
2265     root->appendNew<ControlValue>(
2266         proc, Return, Origin(),
2267         root->appendNew<Value>(
2268             proc, BitXor, Origin(),
2269             root->appendNew<Const64Value>(proc, Origin(), -1),
2270             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2271
2272     CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
2273 }
2274
2275 void testBitNotImm(int64_t a)
2276 {
2277     Procedure proc;
2278     BasicBlock* root = proc.addBlock();
2279     root->appendNew<ControlValue>(
2280         proc, Return, Origin(),
2281         root->appendNew<Value>(
2282             proc, BitXor, Origin(),
2283             root->appendNew<Const64Value>(proc, Origin(), -1),
2284             root->appendNew<Const64Value>(proc, Origin(), a)));
2285
2286     CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
2287 }
2288
2289 void testBitNotMem(int64_t a)
2290 {
2291     Procedure proc;
2292     BasicBlock* root = proc.addBlock();
2293     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2294     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2295     Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
2296         root->appendNew<Const64Value>(proc, Origin(), -1),
2297         load);
2298     root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
2299     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2300
2301     int64_t input = a;
2302     compileAndRun<int32_t>(proc, &input);
2303     CHECK(isIdentical(input, static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
2304 }
2305
2306 void testBitNotArg32(int32_t a)
2307 {
2308     Procedure proc;
2309     BasicBlock* root = proc.addBlock();
2310     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2311         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2312     root->appendNew<ControlValue>(
2313         proc, Return, Origin(),
2314         root->appendNew<Value>(proc, BitXor, Origin(),
2315             root->appendNew<Const32Value>(proc, Origin(), -1),
2316             argument));
2317     CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
2318 }
2319
2320 void testBitNotImm32(int32_t a)
2321 {
2322     Procedure proc;
2323     BasicBlock* root = proc.addBlock();
2324     root->appendNew<ControlValue>(
2325         proc, Return, Origin(),
2326         root->appendNew<Value>(
2327             proc, BitXor, Origin(),
2328             root->appendNew<Const32Value>(proc, Origin(), -1),
2329             root->appendNew<Const32Value>(proc, Origin(), a)));
2330
2331     CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
2332 }
2333
2334 void testBitNotMem32(int32_t a)
2335 {
2336     Procedure proc;
2337     BasicBlock* root = proc.addBlock();
2338     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2339     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2340     Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
2341         root->appendNew<Const32Value>(proc, Origin(), -1),
2342         load);
2343     root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
2344     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2345
2346     int32_t input = a;
2347     compileAndRun<int32_t>(proc, &input);
2348     CHECK(isIdentical(input, static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
2349 }
2350
2351 void testBitNotOnBooleanAndBranch32(int64_t a, int64_t b)
2352 {
2353     Procedure proc;
2354     BasicBlock* root = proc.addBlock();
2355     BasicBlock* thenCase = proc.addBlock();
2356     BasicBlock* elseCase = proc.addBlock();
2357
2358     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
2359         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2360     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
2361         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2362     Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
2363     Value* argsAreNotEqual = root->appendNew<Value>(proc, BitXor, Origin(),
2364         root->appendNew<Const32Value>(proc, Origin(), -1),
2365         argsAreEqual);
2366
2367     root->appendNew<ControlValue>(
2368         proc, Branch, Origin(),
2369         argsAreNotEqual,
2370         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2371
2372     thenCase->appendNew<ControlValue>(
2373         proc, Return, Origin(),
2374         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
2375
2376     elseCase->appendNew<ControlValue>(
2377         proc, Return, Origin(),
2378         elseCase->appendNew<Const32Value>(proc, Origin(), -42));
2379
2380     int32_t expectedValue = (a != b) ? 42 : -42;
2381     CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue);
2382 }
2383
2384 void testShlArgs(int64_t a, int64_t b)
2385 {
2386     Procedure proc;
2387     BasicBlock* root = proc.addBlock();
2388     root->appendNew<ControlValue>(
2389         proc, Return, Origin(),
2390         root->appendNew<Value>(
2391             proc, Shl, Origin(),
2392             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2393             root->appendNew<Value>(
2394                 proc, Trunc, Origin(),
2395                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2396
2397     CHECK(compileAndRun<int64_t>(proc, a, b) == (a << b));
2398 }
2399
2400 void testShlImms(int64_t a, int64_t b)
2401 {
2402     Procedure proc;
2403     BasicBlock* root = proc.addBlock();
2404     root->appendNew<ControlValue>(
2405         proc, Return, Origin(),
2406         root->appendNew<Value>(
2407             proc, Shl, Origin(),
2408             root->appendNew<Const64Value>(proc, Origin(), a),
2409             root->appendNew<Const32Value>(proc, Origin(), b)));
2410
2411     CHECK(compileAndRun<int64_t>(proc) == (a << b));
2412 }
2413
2414 void testShlArgImm(int64_t a, int64_t b)
2415 {
2416     Procedure proc;
2417     BasicBlock* root = proc.addBlock();
2418     root->appendNew<ControlValue>(
2419         proc, Return, Origin(),
2420         root->appendNew<Value>(
2421             proc, Shl, Origin(),
2422             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2423             root->appendNew<Const32Value>(proc, Origin(), b)));
2424
2425     CHECK(compileAndRun<int64_t>(proc, a) == (a << b));
2426 }
2427
2428 void testShlArg32(int32_t a)
2429 {
2430     Procedure proc;
2431     BasicBlock* root = proc.addBlock();
2432     Value* value = root->appendNew<Value>(
2433         proc, Trunc, Origin(),
2434         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2435     root->appendNew<ControlValue>(
2436         proc, Return, Origin(),
2437         root->appendNew<Value>(proc, Shl, Origin(), value, value));
2438
2439     CHECK(compileAndRun<int32_t>(proc, a) == (a << a));
2440 }
2441
2442 void testShlArgs32(int32_t a, int32_t b)
2443 {
2444     Procedure proc;
2445     BasicBlock* root = proc.addBlock();
2446     root->appendNew<ControlValue>(
2447         proc, Return, Origin(),
2448         root->appendNew<Value>(
2449             proc, Shl, Origin(),
2450             root->appendNew<Value>(
2451                 proc, Trunc, Origin(),
2452                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2453             root->appendNew<Value>(
2454                 proc, Trunc, Origin(),
2455                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2456
2457     CHECK(compileAndRun<int32_t>(proc, a, b) == (a << b));
2458 }
2459
2460 void testShlImms32(int32_t a, int32_t b)
2461 {
2462     Procedure proc;
2463     BasicBlock* root = proc.addBlock();
2464     root->appendNew<ControlValue>(
2465         proc, Return, Origin(),
2466         root->appendNew<Value>(
2467             proc, Shl, Origin(),
2468             root->appendNew<Const32Value>(proc, Origin(), a),
2469             root->appendNew<Const32Value>(proc, Origin(), b)));
2470
2471     CHECK(compileAndRun<int32_t>(proc) == (a << b));
2472 }
2473
2474 void testShlArgImm32(int32_t a, int32_t b)
2475 {
2476     Procedure proc;
2477     BasicBlock* root = proc.addBlock();
2478     root->appendNew<ControlValue>(
2479         proc, Return, Origin(),
2480         root->appendNew<Value>(
2481             proc, Shl, Origin(),
2482             root->appendNew<Value>(
2483                 proc, Trunc, Origin(),
2484                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2485             root->appendNew<Const32Value>(proc, Origin(), b)));
2486
2487     CHECK(compileAndRun<int32_t>(proc, a) == (a << b));
2488 }
2489
2490 void testSShrArgs(int64_t a, int64_t b)
2491 {
2492     Procedure proc;
2493     BasicBlock* root = proc.addBlock();
2494     root->appendNew<ControlValue>(
2495         proc, Return, Origin(),
2496         root->appendNew<Value>(
2497             proc, SShr, Origin(),
2498             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2499             root->appendNew<Value>(
2500                 proc, Trunc, Origin(),
2501                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2502
2503     CHECK(compileAndRun<int64_t>(proc, a, b) == (a >> b));
2504 }
2505
2506 void testSShrImms(int64_t a, int64_t b)
2507 {
2508     Procedure proc;
2509     BasicBlock* root = proc.addBlock();
2510     root->appendNew<ControlValue>(
2511         proc, Return, Origin(),
2512         root->appendNew<Value>(
2513             proc, SShr, Origin(),
2514             root->appendNew<Const64Value>(proc, Origin(), a),
2515             root->appendNew<Const32Value>(proc, Origin(), b)));
2516
2517     CHECK(compileAndRun<int64_t>(proc) == (a >> b));
2518 }
2519
2520 void testSShrArgImm(int64_t a, int64_t b)
2521 {
2522     Procedure proc;
2523     BasicBlock* root = proc.addBlock();
2524     root->appendNew<ControlValue>(
2525         proc, Return, Origin(),
2526         root->appendNew<Value>(
2527             proc, SShr, Origin(),
2528             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2529             root->appendNew<Const32Value>(proc, Origin(), b)));
2530
2531     CHECK(compileAndRun<int64_t>(proc, a) == (a >> b));
2532 }
2533
2534 void testSShrArg32(int32_t a)
2535 {
2536     Procedure proc;
2537     BasicBlock* root = proc.addBlock();
2538     Value* value = root->appendNew<Value>(
2539         proc, Trunc, Origin(),
2540         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2541     root->appendNew<ControlValue>(
2542         proc, Return, Origin(),
2543         root->appendNew<Value>(proc, SShr, Origin(), value, value));
2544
2545     CHECK(compileAndRun<int32_t>(proc, a) == (a >> (a & 31)));
2546 }
2547
2548 void testSShrArgs32(int32_t a, int32_t b)
2549 {
2550     Procedure proc;
2551     BasicBlock* root = proc.addBlock();
2552     root->appendNew<ControlValue>(
2553         proc, Return, Origin(),
2554         root->appendNew<Value>(
2555             proc, SShr, Origin(),
2556             root->appendNew<Value>(
2557                 proc, Trunc, Origin(),
2558                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2559             root->appendNew<Value>(
2560                 proc, Trunc, Origin(),
2561                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2562
2563     CHECK(compileAndRun<int32_t>(proc, a, b) == (a >> b));
2564 }
2565
2566 void testSShrImms32(int32_t a, int32_t b)
2567 {
2568     Procedure proc;
2569     BasicBlock* root = proc.addBlock();
2570     root->appendNew<ControlValue>(
2571         proc, Return, Origin(),
2572         root->appendNew<Value>(
2573             proc, SShr, Origin(),
2574             root->appendNew<Const32Value>(proc, Origin(), a),
2575             root->appendNew<Const32Value>(proc, Origin(), b)));
2576
2577     CHECK(compileAndRun<int32_t>(proc) == (a >> b));
2578 }
2579
2580 void testSShrArgImm32(int32_t a, int32_t b)
2581 {
2582     Procedure proc;
2583     BasicBlock* root = proc.addBlock();
2584     root->appendNew<ControlValue>(
2585         proc, Return, Origin(),
2586         root->appendNew<Value>(
2587             proc, SShr, Origin(),
2588             root->appendNew<Value>(
2589                 proc, Trunc, Origin(),
2590                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2591             root->appendNew<Const32Value>(proc, Origin(), b)));
2592
2593     CHECK(compileAndRun<int32_t>(proc, a) == (a >> b));
2594 }
2595
2596 void testZShrArgs(uint64_t a, uint64_t b)
2597 {
2598     Procedure proc;
2599     BasicBlock* root = proc.addBlock();
2600     root->appendNew<ControlValue>(
2601         proc, Return, Origin(),
2602         root->appendNew<Value>(
2603             proc, ZShr, Origin(),
2604             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2605             root->appendNew<Value>(
2606                 proc, Trunc, Origin(),
2607                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2608
2609     CHECK(compileAndRun<uint64_t>(proc, a, b) == (a >> b));
2610 }
2611
2612 void testZShrImms(uint64_t a, uint64_t b)
2613 {
2614     Procedure proc;
2615     BasicBlock* root = proc.addBlock();
2616     root->appendNew<ControlValue>(
2617         proc, Return, Origin(),
2618         root->appendNew<Value>(
2619             proc, ZShr, Origin(),
2620             root->appendNew<Const64Value>(proc, Origin(), a),
2621             root->appendNew<Const32Value>(proc, Origin(), b)));
2622
2623     CHECK(compileAndRun<uint64_t>(proc) == (a >> b));
2624 }
2625
2626 void testZShrArgImm(uint64_t a, uint64_t b)
2627 {
2628     Procedure proc;
2629     BasicBlock* root = proc.addBlock();
2630     root->appendNew<ControlValue>(
2631         proc, Return, Origin(),
2632         root->appendNew<Value>(
2633             proc, ZShr, Origin(),
2634             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2635             root->appendNew<Const32Value>(proc, Origin(), b)));
2636
2637     CHECK(compileAndRun<uint64_t>(proc, a) == (a >> b));
2638 }
2639
2640 void testZShrArg32(uint32_t a)
2641 {
2642     Procedure proc;
2643     BasicBlock* root = proc.addBlock();
2644     Value* value = root->appendNew<Value>(
2645         proc, Trunc, Origin(),
2646         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2647     root->appendNew<ControlValue>(
2648         proc, Return, Origin(),
2649         root->appendNew<Value>(proc, ZShr, Origin(), value, value));
2650
2651     CHECK(compileAndRun<uint32_t>(proc, a) == (a >> (a & 31)));
2652 }
2653
2654 void testZShrArgs32(uint32_t a, uint32_t b)
2655 {
2656     Procedure proc;
2657     BasicBlock* root = proc.addBlock();
2658     root->appendNew<ControlValue>(
2659         proc, Return, Origin(),
2660         root->appendNew<Value>(
2661             proc, ZShr, Origin(),
2662             root->appendNew<Value>(
2663                 proc, Trunc, Origin(),
2664                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2665             root->appendNew<Value>(
2666                 proc, Trunc, Origin(),
2667                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2668
2669     CHECK(compileAndRun<uint32_t>(proc, a, b) == (a >> b));
2670 }
2671
2672 void testZShrImms32(uint32_t a, uint32_t b)
2673 {
2674     Procedure proc;
2675     BasicBlock* root = proc.addBlock();
2676     root->appendNew<ControlValue>(
2677         proc, Return, Origin(),
2678         root->appendNew<Value>(
2679             proc, ZShr, Origin(),
2680             root->appendNew<Const32Value>(proc, Origin(), a),
2681             root->appendNew<Const32Value>(proc, Origin(), b)));
2682
2683     CHECK(compileAndRun<uint32_t>(proc) == (a >> b));
2684 }
2685
2686 void testZShrArgImm32(uint32_t a, uint32_t b)
2687 {
2688     Procedure proc;
2689     BasicBlock* root = proc.addBlock();
2690     root->appendNew<ControlValue>(
2691         proc, Return, Origin(),
2692         root->appendNew<Value>(
2693             proc, ZShr, Origin(),
2694             root->appendNew<Value>(
2695                 proc, Trunc, Origin(),
2696                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2697             root->appendNew<Const32Value>(proc, Origin(), b)));
2698
2699     CHECK(compileAndRun<uint32_t>(proc, a) == (a >> b));
2700 }
2701
2702 template<typename IntegerType>
2703 static unsigned countLeadingZero(IntegerType value)
2704 {
2705     unsigned bitCount = sizeof(IntegerType) * 8;
2706     if (!value)
2707         return bitCount;
2708
2709     unsigned counter = 0;
2710     while (!(static_cast<uint64_t>(value) & (1l << (bitCount - 1)))) {
2711         value <<= 1;
2712         ++counter;
2713     }
2714     return counter;
2715 }
2716
2717 void testClzArg64(int64_t a)
2718 {
2719     Procedure proc;
2720     BasicBlock* root = proc.addBlock();
2721     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2722     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
2723     root->appendNew<ControlValue>(proc, Return, Origin(), clzValue);
2724     CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
2725 }
2726
2727 void testClzMem64(int64_t a)
2728 {
2729     Procedure proc;
2730     BasicBlock* root = proc.addBlock();
2731     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2732     MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2733     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
2734     root->appendNew<ControlValue>(proc, Return, Origin(), clzValue);
2735     CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
2736 }
2737
2738 void testClzArg32(int32_t a)
2739 {
2740     Procedure proc;
2741     BasicBlock* root = proc.addBlock();
2742     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2743         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2744     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
2745     root->appendNew<ControlValue>(proc, Return, Origin(), clzValue);
2746     CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
2747 }
2748
2749 void testClzMem32(int32_t a)
2750 {
2751     Procedure proc;
2752     BasicBlock* root = proc.addBlock();
2753     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2754     MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2755     Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
2756     root->appendNew<ControlValue>(proc, Return, Origin(), clzValue);
2757     CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
2758 }
2759
2760 void testSqrtArg(double a)
2761 {
2762     Procedure proc;
2763     BasicBlock* root = proc.addBlock();
2764     root->appendNew<ControlValue>(
2765         proc, Return, Origin(),
2766         root->appendNew<Value>(
2767             proc, Sqrt, Origin(),
2768                 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
2769
2770     CHECK(isIdentical(compileAndRun<double>(proc, a), sqrt(a)));
2771 }
2772
2773 void testSqrtImm(double a)
2774 {
2775     Procedure proc;
2776     BasicBlock* root = proc.addBlock();
2777     Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2778     root->appendNew<ControlValue>(
2779         proc, Return, Origin(),
2780         root->appendNew<Value>(proc, Sqrt, Origin(), argument));
2781
2782     CHECK(isIdentical(compileAndRun<double>(proc), sqrt(a)));
2783 }
2784
2785 void testSqrtMem(double a)
2786 {
2787     Procedure proc;
2788     BasicBlock* root = proc.addBlock();
2789     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2790     MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
2791     root->appendNew<ControlValue>(
2792         proc, Return, Origin(),
2793         root->appendNew<Value>(proc, Sqrt, Origin(), loadDouble));
2794
2795     CHECK(isIdentical(compileAndRun<double>(proc, &a), sqrt(a)));
2796 }
2797
2798 void testSqrtArg(float a)
2799 {
2800     Procedure proc;
2801     BasicBlock* root = proc.addBlock();
2802     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2803         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2804     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2805     Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument);
2806     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2807     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
2808
2809     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(sqrt(a)))));
2810 }
2811
2812 void testSqrtImm(float a)
2813 {
2814     Procedure proc;
2815     BasicBlock* root = proc.addBlock();
2816     Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2817     Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument);
2818     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2819     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
2820
2821     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(sqrt(a)))));
2822 }
2823
2824 void testSqrtMem(float a)
2825 {
2826     Procedure proc;
2827     BasicBlock* root = proc.addBlock();
2828     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2829     MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
2830     Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), loadFloat);
2831     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2832     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
2833
2834     CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(sqrt(a)))));
2835 }
2836
2837 void testSqrtArgWithUselessDoubleConversion(float a)
2838 {
2839     Procedure proc;
2840     BasicBlock* root = proc.addBlock();
2841     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2842         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2843     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2844     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2845     Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble);
2846     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2847     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2848     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
2849
2850     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(sqrt(a)))));
2851 }
2852
2853 void testSqrtArgWithEffectfulDoubleConversion(float a)
2854 {
2855     Procedure proc;
2856     BasicBlock* root = proc.addBlock();
2857     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2858         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2859     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2860     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2861     Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble);
2862     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2863     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2864     Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2865     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
2866     root->appendNew<ControlValue>(proc, Return, Origin(), result32);
2867
2868     double effect = 0;
2869     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect), bitwise_cast<int32_t>(static_cast<float>(sqrt(a)))));
2870     CHECK(isIdentical(effect, sqrt(a)));
2871 }
2872
2873 void testDoubleArgToInt64BitwiseCast(double value)
2874 {
2875     Procedure proc;
2876     BasicBlock* root = proc.addBlock();
2877     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2878
2879     root->appendNew<ControlValue>(
2880         proc, Return, Origin(),
2881         root->appendNew<Value>(
2882             proc, BitwiseCast, Origin(), argument));
2883
2884     CHECK(isIdentical(compileAndRun<int64_t>(proc, value), bitwise_cast<int64_t>(value)));
2885 }
2886
2887 void testDoubleImmToInt64BitwiseCast(double value)
2888 {
2889     Procedure proc;
2890     BasicBlock* root = proc.addBlock();
2891     Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value);
2892
2893     root->appendNew<ControlValue>(
2894         proc, Return, Origin(),
2895         root->appendNew<Value>(
2896             proc, BitwiseCast, Origin(), argument));
2897
2898     CHECK(isIdentical(compileAndRun<int64_t>(proc), bitwise_cast<int64_t>(value)));
2899 }
2900
2901 void testTwoBitwiseCastOnDouble(double value)
2902 {
2903     Procedure proc;
2904     BasicBlock* root = proc.addBlock();
2905     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2906     Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
2907     Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
2908     root->appendNew<ControlValue>(proc, Return, Origin(), second);
2909
2910     CHECK(isIdentical(compileAndRun<double>(proc, value), value));
2911 }
2912
2913 void testBitwiseCastOnDoubleInMemory(double value)
2914 {
2915     Procedure proc;
2916     BasicBlock* root = proc.addBlock();
2917     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2918     MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
2919     Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
2920     root->appendNew<ControlValue>(proc, Return, Origin(), cast);
2921
2922     CHECK(isIdentical(compileAndRun<int64_t>(proc, &value), bitwise_cast<int64_t>(value)));
2923 }
2924
2925 void testInt64BArgToDoubleBitwiseCast(int64_t value)
2926 {
2927     Procedure proc;
2928     BasicBlock* root = proc.addBlock();
2929     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2930
2931     root->appendNew<ControlValue>(
2932         proc, Return, Origin(),
2933         root->appendNew<Value>(
2934             proc, BitwiseCast, Origin(), argument));
2935
2936     CHECK(isIdentical(compileAndRun<double>(proc, value), bitwise_cast<double>(value)));
2937 }
2938
2939 void testInt64BImmToDoubleBitwiseCast(int64_t value)
2940 {
2941     Procedure proc;
2942     BasicBlock* root = proc.addBlock();
2943     Value* argument = root->appendNew<Const64Value>(proc, Origin(), value);
2944
2945     root->appendNew<ControlValue>(
2946         proc, Return, Origin(),
2947         root->appendNew<Value>(
2948             proc, BitwiseCast, Origin(), argument));
2949
2950     CHECK(isIdentical(compileAndRun<double>(proc), bitwise_cast<double>(value)));
2951 }
2952
2953 void testTwoBitwiseCastOnInt64(int64_t value)
2954 {
2955     Procedure proc;
2956     BasicBlock* root = proc.addBlock();
2957     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2958     Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
2959     Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
2960     root->appendNew<ControlValue>(proc, Return, Origin(), second);
2961
2962     CHECK(isIdentical(compileAndRun<int64_t>(proc, value), value));
2963 }
2964
2965 void testBitwiseCastOnInt64InMemory(int64_t value)
2966 {
2967     Procedure proc;
2968     BasicBlock* root = proc.addBlock();
2969     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2970     MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2971     Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
2972     root->appendNew<ControlValue>(proc, Return, Origin(), cast);
2973
2974     CHECK(isIdentical(compileAndRun<double>(proc, &value), bitwise_cast<double>(value)));
2975 }
2976
2977 void testFloatImmToInt32BitwiseCast(float value)
2978 {
2979     Procedure proc;
2980     BasicBlock* root = proc.addBlock();
2981     Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value);
2982
2983     root->appendNew<ControlValue>(
2984         proc, Return, Origin(),
2985         root->appendNew<Value>(
2986             proc, BitwiseCast, Origin(), argument));
2987
2988     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(value)));
2989 }
2990
2991 void testBitwiseCastOnFloatInMemory(float value)
2992 {
2993     Procedure proc;
2994     BasicBlock* root = proc.addBlock();
2995     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2996     MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
2997     Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat);
2998     root->appendNew<ControlValue>(proc, Return, Origin(), cast);
2999
3000     CHECK(isIdentical(compileAndRun<int32_t>(proc, &value), bitwise_cast<int32_t>(value)));
3001 }
3002
3003 void testInt32BArgToFloatBitwiseCast(int32_t value)
3004 {
3005     Procedure proc;
3006     BasicBlock* root = proc.addBlock();
3007     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3008
3009     root->appendNew<ControlValue>(
3010         proc, Return, Origin(),
3011         root->appendNew<Value>(
3012             proc, BitwiseCast, Origin(), argument));
3013
3014     CHECK(isIdentical(compileAndRun<float>(proc, value), bitwise_cast<float>(value)));
3015 }
3016
3017 void testInt32BImmToFloatBitwiseCast(int32_t value)
3018 {
3019     Procedure proc;
3020     BasicBlock* root = proc.addBlock();
3021     Value* argument = root->appendNew<Const64Value>(proc, Origin(), value);
3022
3023     root->appendNew<ControlValue>(
3024         proc, Return, Origin(),
3025         root->appendNew<Value>(
3026             proc, BitwiseCast, Origin(), argument));
3027
3028     CHECK(isIdentical(compileAndRun<float>(proc), bitwise_cast<float>(value)));
3029 }
3030
3031 void testTwoBitwiseCastOnInt32(int32_t value)
3032 {
3033     Procedure proc;
3034     BasicBlock* root = proc.addBlock();
3035     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3036     Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
3037     Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
3038     root->appendNew<ControlValue>(proc, Return, Origin(), second);
3039
3040     CHECK(isIdentical(compileAndRun<int32_t>(proc, value), value));
3041 }
3042
3043 void testBitwiseCastOnInt32InMemory(int32_t value)
3044 {
3045     Procedure proc;
3046     BasicBlock* root = proc.addBlock();
3047     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3048     MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
3049     Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat);
3050     root->appendNew<ControlValue>(proc, Return, Origin(), cast);
3051
3052     CHECK(isIdentical(compileAndRun<float>(proc, &value), bitwise_cast<float>(value)));
3053 }
3054
3055 void testConvertDoubleToFloatArg(double value)
3056 {
3057     Procedure proc;
3058     BasicBlock* root = proc.addBlock();
3059     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3060     Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
3061     root->appendNew<ControlValue>(proc, Return, Origin(), asFloat);
3062
3063     CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value)));
3064 }
3065
3066 void testConvertDoubleToFloatImm(double value)
3067 {
3068     Procedure proc;
3069     BasicBlock* root = proc.addBlock();
3070     Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value);
3071     Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
3072     root->appendNew<ControlValue>(proc, Return, Origin(), asFloat);
3073
3074     CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
3075 }
3076
3077 void testConvertDoubleToFloatMem(double value)
3078 {
3079     Procedure proc;
3080     BasicBlock* root = proc.addBlock();
3081     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3082     MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
3083     Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble);
3084     root->appendNew<ControlValue>(proc, Return, Origin(), asFloat);
3085
3086     CHECK(isIdentical(compileAndRun<float>(proc, &value), static_cast<float>(value)));
3087 }
3088
3089 void testConvertFloatToDoubleArg(float value)
3090 {
3091     Procedure proc;
3092     BasicBlock* root = proc.addBlock();
3093     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
3094         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3095     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
3096     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
3097     root->appendNew<ControlValue>(proc, Return, Origin(), asDouble);
3098
3099     CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int32_t>(value)), static_cast<double>(value)));
3100 }
3101
3102 void testConvertFloatToDoubleImm(float value)
3103 {
3104     Procedure proc;
3105     BasicBlock* root = proc.addBlock();
3106     Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value);
3107     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument);
3108     root->appendNew<ControlValue>(proc, Return, Origin(), asDouble);
3109
3110     CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
3111 }
3112
3113 void testConvertFloatToDoubleMem(float value)
3114 {
3115     Procedure proc;
3116     BasicBlock* root = proc.addBlock();
3117     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3118     MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
3119     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat);
3120     root->appendNew<ControlValue>(proc, Return, Origin(), asDouble);
3121
3122     CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(value)));
3123 }
3124
3125 void testConvertDoubleToFloatToDoubleToFloat(double value)
3126 {
3127     Procedure proc;
3128     BasicBlock* root = proc.addBlock();
3129     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3130     Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
3131     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
3132     Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble);
3133     root->appendNew<ControlValue>(proc, Return, Origin(), asFloatAgain);
3134
3135     CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value)));
3136 }
3137
3138 void testLoadFloatConvertDoubleConvertFloatStoreFloat(float value)
3139 {
3140     Procedure proc;
3141     BasicBlock* root = proc.addBlock();
3142     Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3143     Value* dst = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3144     MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), src);
3145     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat);
3146     Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble);
3147     root->appendNew<MemoryValue>(proc, Store, Origin(), asFloatAgain, dst);
3148
3149     root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3150
3151     float input = value;
3152     float output = 0.;
3153     CHECK(!compileAndRun<int64_t>(proc, &input, &output));
3154     CHECK(isIdentical(input, output));
3155 }
3156
3157 void testFroundArg(double value)
3158 {
3159     Procedure proc;
3160     BasicBlock* root = proc.addBlock();
3161     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3162     Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
3163     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
3164     root->appendNew<ControlValue>(proc, Return, Origin(), asDouble);
3165
3166     CHECK(isIdentical(compileAndRun<double>(proc, value), static_cast<double>(static_cast<float>(value))));
3167 }
3168
3169 void testFroundMem(double value)
3170 {
3171     Procedure proc;
3172     BasicBlock* root = proc.addBlock();
3173     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3174     MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
3175     Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble);
3176     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
3177     root->appendNew<ControlValue>(proc, Return, Origin(), asDouble);
3178
3179     CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(static_cast<float>(value))));
3180 }
3181
3182 void testStore32(int value)
3183 {
3184     Procedure proc;
3185     BasicBlock* root = proc.addBlock();
3186     int slot = 0xbaadbeef;
3187     root->appendNew<MemoryValue>(
3188         proc, Store, Origin(),
3189         root->appendNew<Value>(
3190             proc, Trunc, Origin(),
3191             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3192         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
3193     root->appendNew<ControlValue>(
3194         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3195
3196     CHECK(!compileAndRun<int>(proc, value));
3197     CHECK(slot == value);
3198 }
3199
3200 void testStoreConstant(int value)
3201 {
3202     Procedure proc;
3203     BasicBlock* root = proc.addBlock();
3204     int slot = 0xbaadbeef;
3205     root->appendNew<MemoryValue>(
3206         proc, Store, Origin(),
3207         root->appendNew<Const32Value>(proc, Origin(), value),
3208         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
3209     root->appendNew<ControlValue>(
3210         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3211
3212     CHECK(!compileAndRun<int>(proc));
3213     CHECK(slot == value);
3214 }
3215
3216 void testStoreConstantPtr(intptr_t value)
3217 {
3218     Procedure proc;
3219     BasicBlock* root = proc.addBlock();
3220     intptr_t slot;
3221     if (is64Bit())
3222         slot = (static_cast<intptr_t>(0xbaadbeef) << 32) + static_cast<intptr_t>(0xbaadbeef);
3223     else
3224         slot = 0xbaadbeef;
3225     root->appendNew<MemoryValue>(
3226         proc, Store, Origin(),
3227         root->appendNew<ConstPtrValue>(proc, Origin(), value),
3228         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
3229     root->appendNew<ControlValue>(
3230         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3231
3232     CHECK(!compileAndRun<int>(proc));
3233     CHECK(slot == value);
3234 }
3235
3236 void testTrunc(int64_t value)
3237 {
3238     Procedure proc;
3239     BasicBlock* root = proc.addBlock();
3240     root->appendNew<ControlValue>(
3241         proc, Return, Origin(),
3242         root->appendNew<Value>(
3243             proc, Trunc, Origin(),
3244             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3245
3246     CHECK(compileAndRun<int>(proc, value) == static_cast<int>(value));
3247 }
3248
3249 void testAdd1(int value)
3250 {
3251     Procedure proc;
3252     BasicBlock* root = proc.addBlock();
3253     root->appendNew<ControlValue>(
3254         proc, Return, Origin(),
3255         root->appendNew<Value>(
3256             proc, Add, Origin(),
3257             root->appendNew<Value>(
3258                 proc, Trunc, Origin(),
3259                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3260             root->appendNew<Const32Value>(proc, Origin(), 1)));
3261
3262     CHECK(compileAndRun<int>(proc, value) == value + 1);
3263 }
3264
3265 void testAdd1Ptr(intptr_t value)
3266 {
3267     Procedure proc;
3268     BasicBlock* root = proc.addBlock();
3269     root->appendNew<ControlValue>(
3270         proc, Return, Origin(),
3271         root->appendNew<Value>(
3272             proc, Add, Origin(),
3273             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3274             root->appendNew<ConstPtrValue>(proc, Origin(), 1)));
3275
3276     CHECK(compileAndRun<intptr_t>(proc, value) == value + 1);
3277 }
3278
3279 void testNeg32(int32_t value)
3280 {
3281     Procedure proc;
3282     BasicBlock* root = proc.addBlock();
3283     root->appendNew<ControlValue>(
3284         proc, Return, Origin(),
3285         root->appendNew<Value>(
3286             proc, Sub, Origin(),
3287             root->appendNew<Const32Value>(proc, Origin(), 0),
3288             root->appendNew<Value>(
3289                 proc, Trunc, Origin(),
3290                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3291
3292     CHECK(compileAndRun<int32_t>(proc, value) == -value);
3293 }
3294
3295 void testNegPtr(intptr_t value)
3296 {
3297     Procedure proc;
3298     BasicBlock* root = proc.addBlock();
3299     root->appendNew<ControlValue>(
3300         proc, Return, Origin(),
3301         root->appendNew<Value>(
3302             proc, Sub, Origin(),
3303             root->appendNew<ConstPtrValue>(proc, Origin(), 0),
3304             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3305
3306     CHECK(compileAndRun<intptr_t>(proc, value) == -value);
3307 }
3308
3309 void testStoreAddLoad(int amount)
3310 {
3311     Procedure proc;
3312     BasicBlock* root = proc.addBlock();
3313     int slot = 37;
3314     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
3315     root->appendNew<MemoryValue>(
3316         proc, Store, Origin(),
3317         root->appendNew<Value>(
3318             proc, Add, Origin(),
3319             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
3320             root->appendNew<Const32Value>(proc, Origin(), amount)),
3321         slotPtr);
3322     root->appendNew<ControlValue>(
3323         proc, Return, Origin(),
3324         root->appendNew<Const32Value>(proc, Origin(), 0));
3325
3326     CHECK(!compileAndRun<int>(proc));
3327     CHECK(slot == 37 + amount);
3328 }
3329
3330 void testStoreSubLoad(int amount)
3331 {
3332     Procedure proc;
3333     BasicBlock* root = proc.addBlock();
3334     int32_t startValue = std::numeric_limits<int32_t>::min();
3335     int32_t slot = startValue;
3336     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
3337     root->appendNew<MemoryValue>(
3338         proc, Store, Origin(),
3339         root->appendNew<Value>(
3340             proc, Sub, Origin(),
3341             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
3342             root->appendNew<Value>(
3343                 proc, Trunc, Origin(),
3344                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
3345         slotPtr);
3346     root->appendNew<ControlValue>(
3347         proc, Return, Origin(),
3348         root->appendNew<Const32Value>(proc, Origin(), 0));
3349
3350     CHECK(!compileAndRun<int>(proc, amount));
3351     CHECK(slot == startValue - amount);
3352 }
3353
3354 void testStoreAddLoadInterference(int amount)
3355 {
3356     Procedure proc;
3357     BasicBlock* root = proc.addBlock();
3358     int slot = 37;
3359     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
3360     ArgumentRegValue* otherSlotPtr =
3361         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3362     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr);
3363     root->appendNew<MemoryValue>(
3364         proc, Store, Origin(),
3365         root->appendNew<Const32Value>(proc, Origin(), 666),
3366         otherSlotPtr);
3367     root->appendNew<MemoryValue>(
3368         proc, Store, Origin(),
3369         root->appendNew<Value>(
3370             proc, Add, Origin(),
3371             load, root->appendNew<Const32Value>(proc, Origin(), amount)),
3372         slotPtr);
3373     root->appendNew<ControlValue>(
3374         proc, Return, Origin(),
3375         root->appendNew<Const32Value>(proc, Origin(), 0));
3376
3377     CHECK(!compileAndRun<int>(proc, &slot));
3378     CHECK(slot == 37 + amount);
3379 }
3380
3381 void testStoreAddAndLoad(int amount, int mask)
3382 {
3383     Procedure proc;
3384     BasicBlock* root = proc.addBlock();
3385     int slot = 37;
3386     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
3387     root->appendNew<MemoryValue>(
3388         proc, Store, Origin(),
3389         root->appendNew<Value>(
3390             proc, BitAnd, Origin(),
3391             root->appendNew<Value>(
3392                 proc, Add, Origin(),
3393                 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
3394                 root->appendNew<Const32Value>(proc, Origin(), amount)),
3395             root->appendNew<Const32Value>(proc, Origin(), mask)),
3396         slotPtr);
3397     root->appendNew<ControlValue>(
3398         proc, Return, Origin(),
3399         root->appendNew<Const32Value>(proc, Origin(), 0));
3400
3401     CHECK(!compileAndRun<int>(proc));
3402     CHECK(slot == ((37 + amount) & mask));
3403 }
3404
3405 void testStoreNegLoad32(int32_t value)
3406 {
3407     Procedure proc;
3408     BasicBlock* root = proc.addBlock();
3409
3410     int32_t slot = value;
3411
3412     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
3413     
3414     root->appendNew<MemoryValue>(
3415         proc, Store, Origin(),
3416         root->appendNew<Value>(
3417             proc, Sub, Origin(),
3418             root->appendNew<Const32Value>(proc, Origin(), 0),
3419             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)),
3420         slotPtr);
3421     
3422     root->appendNew<ControlValue>(
3423         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3424
3425     CHECK(!compileAndRun<int32_t>(proc));
3426     CHECK(slot == -value);
3427 }
3428
3429 void testStoreNegLoadPtr(intptr_t value)
3430 {
3431     Procedure proc;
3432     BasicBlock* root = proc.addBlock();
3433
3434     intptr_t slot = value;
3435
3436     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
3437     
3438     root->appendNew<MemoryValue>(
3439         proc, Store, Origin(),
3440         root->appendNew<Value>(
3441             proc, Sub, Origin(),
3442             root->appendNew<ConstPtrValue>(proc, Origin(), 0),
3443             root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)),
3444         slotPtr);
3445     
3446     root->appendNew<ControlValue>(
3447         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3448
3449     CHECK(!compileAndRun<int32_t>(proc));
3450     CHECK(slot == -value);
3451 }
3452
3453 void testAdd1Uncommuted(int value)
3454 {
3455     Procedure proc;
3456     BasicBlock* root = proc.addBlock();
3457     root->appendNew<ControlValue>(
3458         proc, Return, Origin(),
3459         root->appendNew<Value>(
3460             proc, Add, Origin(),
3461             root->appendNew<Const32Value>(proc, Origin(), 1),
3462             root->appendNew<Value>(
3463                 proc, Trunc, Origin(),
3464                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3465
3466     CHECK(compileAndRun<int>(proc, value) == value + 1);
3467 }
3468
3469 void testLoadOffset()
3470 {
3471     Procedure proc;
3472     BasicBlock* root = proc.addBlock();
3473     int array[] = { 1, 2 };
3474     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
3475     root->appendNew<ControlValue>(
3476         proc, Return, Origin(),
3477         root->appendNew<Value>(
3478             proc, Add, Origin(),
3479             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
3480             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int))));
3481
3482     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
3483 }
3484
3485 void testLoadOffsetNotConstant()
3486 {
3487     Procedure proc;
3488     BasicBlock* root = proc.addBlock();
3489     int array[] = { 1, 2 };
3490     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3491     root->appendNew<ControlValue>(
3492         proc, Return, Origin(),
3493         root->appendNew<Value>(
3494             proc, Add, Origin(),
3495             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
3496             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int))));
3497
3498     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
3499 }
3500
3501 void testLoadOffsetUsingAdd()
3502 {
3503     Procedure proc;
3504     BasicBlock* root = proc.addBlock();
3505     int array[] = { 1, 2 };
3506     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
3507     root->appendNew<ControlValue>(
3508         proc, Return, Origin(),
3509         root->appendNew<Value>(
3510             proc, Add, Origin(),
3511             root->appendNew<MemoryValue>(
3512                 proc, Load, Int32, Origin(),
3513                 root->appendNew<Value>(
3514                     proc, Add, Origin(), arrayPtr,
3515                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
3516             root->appendNew<MemoryValue>(
3517                 proc, Load, Int32, Origin(),
3518                 root->appendNew<Value>(
3519                     proc, Add, Origin(), arrayPtr,
3520                     root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
3521     
3522     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
3523 }
3524
3525 void testLoadOffsetUsingAddInterference()
3526 {
3527     Procedure proc;
3528     BasicBlock* root = proc.addBlock();
3529     int array[] = { 1, 2 };
3530     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
3531     ArgumentRegValue* otherArrayPtr =
3532         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3533     Const32Value* theNumberOfTheBeast = root->appendNew<Const32Value>(proc, Origin(), 666);
3534     MemoryValue* left = root->appendNew<MemoryValue>(
3535         proc, Load, Int32, Origin(),
3536         root->appendNew<Value>(
3537             proc, Add, Origin(), arrayPtr,
3538             root->appendNew<ConstPtrValue>(proc, Origin(), 0)));
3539     MemoryValue* right = root->appendNew<MemoryValue>(
3540         proc, Load, Int32, Origin(),
3541         root->appendNew<Value>(
3542             proc, Add, Origin(), arrayPtr,
3543             root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))));
3544     root->appendNew<MemoryValue>(
3545         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0);
3546     root->appendNew<MemoryValue>(
3547         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, sizeof(int));
3548     root->appendNew<ControlValue>(
3549         proc, Return, Origin(),
3550         root->appendNew<Value>(
3551             proc, Add, Origin(), left, right));
3552     
3553     CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2);
3554     CHECK(array[0] == 666);
3555     CHECK(array[1] == 666);
3556 }
3557
3558 void testLoadOffsetUsingAddNotConstant()
3559 {
3560     Procedure proc;
3561     BasicBlock* root = proc.addBlock();
3562     int array[] = { 1, 2 };
3563     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3564     root->appendNew<ControlValue>(
3565         proc, Return, Origin(),
3566         root->appendNew<Value>(
3567             proc, Add, Origin(),
3568             root->appendNew<MemoryValue>(
3569                 proc, Load, Int32, Origin(),
3570                 root->appendNew<Value>(
3571                     proc, Add, Origin(), arrayPtr,
3572                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
3573             root->appendNew<MemoryValue>(
3574                 proc, Load, Int32, Origin(),
3575                 root->appendNew<Value>(
3576                     proc, Add, Origin(), arrayPtr,
3577                     root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
3578     
3579     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
3580 }
3581
3582 void testLoadAddrShift(unsigned shift)
3583 {
3584     Procedure proc;
3585     BasicBlock* root = proc.addBlock();
3586     int slots[2];
3587
3588     // Figure out which slot to use while having proper alignment for the shift.
3589     int* slot;
3590     uintptr_t arg;
3591     for (unsigned i = sizeof(slots)/sizeof(slots[0]); i--;) {
3592         slot = slots + i;
3593         arg = bitwise_cast<uintptr_t>(slot) >> shift;
3594         if (bitwise_cast<int*>(arg << shift) == slot)
3595             break;
3596     }
3597
3598     *slot = 8675309;
3599     
3600     root->appendNew<ControlValue>(
3601         proc, Return, Origin(),
3602         root->appendNew<MemoryValue>(
3603             proc, Load, Int32, Origin(),
3604             root->appendNew<Value>(
3605                 proc, Shl, Origin(),
3606                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3607                 root->appendNew<Const32Value>(proc, Origin(), shift))));
3608
3609     CHECK(compileAndRun<int>(proc, arg) == 8675309);
3610 }
3611
3612 void testFramePointer()
3613 {
3614     Procedure proc;
3615     BasicBlock* root = proc.addBlock();
3616     root->appendNew<ControlValue>(
3617         proc, Return, Origin(),
3618         root->appendNew<Value>(proc, FramePointer, Origin()));
3619
3620     void* fp = compileAndRun<void*>(proc);
3621     CHECK(fp < &proc);
3622     CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
3623 }
3624
3625 void testStackSlot()
3626 {
3627     Procedure proc;
3628     BasicBlock* root = proc.addBlock();
3629     root->appendNew<ControlValue>(
3630         proc, Return, Origin(),
3631         root->appendNew<StackSlotValue>(proc, Origin(), 1, StackSlotKind::Anonymous));
3632
3633     void* stackSlot = compileAndRun<void*>(proc);
3634     CHECK(stackSlot < &proc);
3635     CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000);
3636 }
3637
3638 void testLoadFromFramePointer()
3639 {
3640     Procedure proc;
3641     BasicBlock* root = proc.addBlock();
3642     root->appendNew<ControlValue>(
3643         proc, Return, Origin(),
3644         root->appendNew<MemoryValue>(
3645             proc, Load, pointerType(), Origin(),
3646             root->appendNew<Value>(proc, FramePointer, Origin())));
3647
3648     void* fp = compileAndRun<void*>(proc);
3649     void* myFP = __builtin_frame_address(0);
3650     CHECK(fp <= myFP);
3651     CHECK(fp >= bitwise_cast<char*>(myFP) - 10000);
3652 }
3653
3654 void testStoreLoadStackSlot(int value)
3655 {
3656     Procedure proc;
3657     BasicBlock* root = proc.addBlock();
3658
3659     StackSlotValue* stack = root->appendNew<StackSlotValue>(
3660         proc, Origin(), sizeof(int), StackSlotKind::Anonymous);
3661
3662     root->appendNew<MemoryValue>(
3663         proc, Store, Origin(),
3664         root->appendNew<Value>(
3665             proc, Trunc, Origin(),
3666             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3667         stack);
3668     
3669     root->appendNew<ControlValue>(
3670         proc, Return, Origin(),
3671         root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack));
3672
3673     CHECK(compileAndRun<int>(proc, value) == value);
3674 }
3675
3676 template<typename LoadedType, typename EffectiveType>
3677 EffectiveType modelLoad(EffectiveType value)
3678 {
3679     union {
3680         EffectiveType original;
3681         LoadedType loaded;
3682     } u;
3683
3684     u.original = value;
3685     if (std::is_signed<LoadedType>::value)
3686         return static_cast<EffectiveType>(u.loaded);
3687     return static_cast<EffectiveType>(static_cast<typename std::make_unsigned<EffectiveType>::type>(u.loaded));
3688 }
3689
3690 template<>
3691 float modelLoad<float, float>(float value) { return value; }
3692
3693 template<>
3694 double modelLoad<double, double>(double value) { return value; }
3695
3696 template<B3::Type type, typename CType, typename InputType>
3697 void testLoad(B3::Opcode opcode, InputType value)
3698 {
3699     // Simple load from an absolute address.
3700     {
3701         Procedure proc;
3702         BasicBlock* root = proc.addBlock();
3703         
3704         root->appendNew<ControlValue>(
3705             proc, Return, Origin(),
3706             root->appendNew<MemoryValue>(
3707                 proc, opcode, type, Origin(),
3708                 root->appendNew<ConstPtrValue>(proc, Origin(), &value)));
3709
3710         CHECK(isIdentical(compileAndRun<CType>(proc), modelLoad<CType>(value)));
3711     }
3712     
3713     // Simple load from an address in a register.
3714     {
3715         Procedure proc;
3716         BasicBlock* root = proc.addBlock();
3717         
3718         root->appendNew<ControlValue>(
3719             proc, Return, Origin(),
3720             root->appendNew<MemoryValue>(
3721                 proc, opcode, type, Origin(),
3722                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3723
3724         CHECK(isIdentical(compileAndRun<CType>(proc, &value), modelLoad<CType>(value)));
3725     }
3726     
3727     // Simple load from an address in a register, at an offset.
3728     {
3729         Procedure proc;
3730         BasicBlock* root = proc.addBlock();
3731         
3732         root->appendNew<ControlValue>(
3733             proc, Return, Origin(),
3734             root->appendNew<MemoryValue>(
3735                 proc, opcode, type, Origin(),
3736                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3737                 sizeof(InputType)));
3738
3739         CHECK(isIdentical(compileAndRun<CType>(proc, &value - 1), modelLoad<CType>(value)));
3740     }
3741
3742     // Load from a simple base-index with various scales.
3743     for (unsigned logScale = 0; logScale <= 3; ++logScale) {
3744         Procedure proc;
3745         BasicBlock* root = proc.addBlock();
3746
3747         root->appendNew<ControlValue>(
3748             proc, Return, Origin(),
3749             root->appendNew<MemoryValue>(
3750                 proc, opcode, type, Origin(),
3751                 root->appendNew<Value>(
3752                     proc, Add, Origin(),
3753                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3754                     root->appendNew<Value>(
3755                         proc, Shl, Origin(),
3756                         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
3757                         root->appendNew<Const32Value>(proc, Origin(), logScale)))));
3758
3759         CHECK(isIdentical(compileAndRun<CType>(proc, &value - 2, (sizeof(InputType) * 2) >> logScale), modelLoad<CType>(value)));
3760     }
3761
3762     // Load from a simple base-index with various scales, but commuted.
3763     for (unsigned logScale = 0; logScale <= 3; ++logScale) {
3764         Procedure proc;
3765         BasicBlock* root = proc.addBlock();
3766
3767         root->appendNew<ControlValue>(
3768             proc, Return, Origin(),
3769             root->appendNew<MemoryValue>(
3770                 proc, opcode, type, Origin(),
3771                 root->appendNew<Value>(
3772                     proc, Add, Origin(),
3773                     root->appendNew<Value>(
3774                         proc, Shl, Origin(),
3775                         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
3776                         root->appendNew<Const32Value>(proc, Origin(), logScale)),
3777                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3778
3779         CHECK(isIdentical(compileAndRun<CType>(proc, &value - 2, (sizeof(InputType) * 2) >> logScale), modelLoad<CType>(value)));
3780     }
3781 }
3782
3783 template<typename T>
3784 void testLoad(B3::Opcode opcode, int32_t value)
3785 {
3786     return testLoad<Int32, T>(opcode, value);
3787 }
3788
3789 template<B3::Type type, typename T>
3790 void testLoad(T value)
3791 {
3792     return testLoad<type, T>(Load, value);
3793 }
3794
3795 void testStoreFloat(double input)
3796 {
3797     // Simple store from an address in a register.
3798     {
3799         Procedure proc;
3800         BasicBlock* root = proc.addBlock();
3801         Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3802         Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
3803
3804         Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3805         root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
3806
3807         root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3808
3809         float output = 0.;
3810         CHECK(!compileAndRun<int64_t>(proc, input, &output));
3811         CHECK(isIdentical(static_cast<float>(input), output));
3812     }
3813
3814     // Simple indexed store.
3815     {
3816         Procedure proc;
3817         BasicBlock* root = proc.addBlock();
3818         Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3819         Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
3820
3821         Value* destinationBaseAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3822         Value* index = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3823         Value* scaledIndex = root->appendNew<Value>(
3824             proc, Shl, Origin(),
3825             index,
3826             root->appendNew<Const32Value>(proc, Origin(), 2));
3827         Value* destinationAddress = root->appendNew<Value>(proc, Add, Origin(), scaledIndex, destinationBaseAddress);
3828
3829         root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
3830
3831         root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3832
3833         float output = 0.;
3834         CHECK(!compileAndRun<int64_t>(proc, input, &output - 1, 1));
3835         CHECK(isIdentical(static_cast<float>(input), output));
3836     }
3837 }
3838
3839 void testSpillGP()
3840 {
3841     Procedure proc;
3842     BasicBlock* root = proc.addBlock();
3843
3844     Vector<Value*> sources;
3845     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3846     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3847
3848     for (unsigned i = 0; i < 30; ++i) {
3849         sources.append(
3850             root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
3851         );
3852     }
3853
3854     Value* total = root->appendNew<Const64Value>(proc, Origin(), 0);
3855     for (Value* value : sources)
3856         total = root->appendNew<Value>(proc, Add, Origin(), total, value);
3857
3858     root->appendNew<ControlValue>(proc, Return, Origin(), total);
3859     compileAndRun<int>(proc, 1, 2);
3860 }
3861
3862 void testSpillFP()
3863 {
3864     Procedure proc;
3865     BasicBlock* root = proc.addBlock();
3866
3867     Vector<Value*> sources;
3868     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
3869     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
3870
3871     for (unsigned i = 0; i < 30; ++i) {
3872         sources.append(
3873             root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
3874         );
3875     }
3876
3877     Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
3878     for (Value* value : sources)
3879         total = root->appendNew<Value>(proc, Add, Origin(), total, value);
3880
3881     root->appendNew<ControlValue>(proc, Return, Origin(), total);
3882     compileAndRun<double>(proc, 1.1, 2.5);
3883 }
3884
3885 void testInt32ToDoublePartialRegisterStall()
3886 {
3887     Procedure proc;
3888     BasicBlock* root = proc.addBlock();
3889     BasicBlock* loop = proc.addBlock();
3890     BasicBlock* done = proc.addBlock();
3891
3892     // Head.
3893     Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
3894     Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3895     UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
3896     UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
3897     root->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loop));
3898
3899     // Loop.
3900     Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
3901     Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
3902     originalCounter->setPhi(loopCounter);
3903     originalTotal->setPhi(loopTotal);
3904
3905     Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
3906     Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
3907     Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
3908     UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
3909     updatedTotalUpsilon->setPhi(loopTotal);
3910
3911     Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
3912     UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
3913     decCounterUpsilon->setPhi(loopCounter);
3914     loop->appendNew<ControlValue>(
3915         proc, Branch, Origin(),
3916         decCounter,
3917         FrequentedBlock(loop), FrequentedBlock(done));
3918
3919     // Tail.
3920     done->appendNew<ControlValue>(proc, Return, Origin(), updatedTotal);
3921     CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
3922 }
3923
3924 void testInt32ToDoublePartialRegisterWithoutStall()
3925 {
3926     Procedure proc;
3927     BasicBlock* root = proc.addBlock();
3928     BasicBlock* loop = proc.addBlock();
3929     BasicBlock* done = proc.addBlock();
3930
3931     // Head.
3932     Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
3933     Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3934     UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
3935     UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
3936     uint64_t forPaddingInput;
3937     Value* forPaddingInputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingInput);
3938     uint64_t forPaddingOutput;
3939     Value* forPaddingOutputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingOutput);
3940     root->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loop));
3941
3942     // Loop.
3943     Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
3944     Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
3945     originalCounter->setPhi(loopCounter);
3946     originalTotal->setPhi(loopTotal);
3947
3948     Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
3949     Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
3950     Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
3951
3952     // Add enough padding instructions to avoid a stall.
3953     Value* loadPadding = loop->appendNew<MemoryValue>(proc, Load, Int64, Origin(), forPaddingInputAddress);
3954     Value* padding = loop->appendNew<Value>(proc, BitXor, Origin(), loadPadding, loopCounter);
3955     padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
3956     padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
3957     padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
3958     padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
3959     padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
3960     padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
3961     padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
3962     padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
3963     padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
3964     padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
3965     padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
3966     loop->appendNew<MemoryValue>(proc, Store, Origin(), padding, forPaddingOutputAddress);
3967
3968     UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
3969     updatedTotalUpsilon->setPhi(loopTotal);
3970
3971     Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
3972     UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
3973     decCounterUpsilon->setPhi(loopCounter);
3974     loop->appendNew<ControlValue>(
3975         proc, Branch, Origin(),
3976         decCounter,
3977         FrequentedBlock(loop), FrequentedBlock(done));
3978
3979     // Tail.
3980     done->appendNew<ControlValue>(proc, Return, Origin(), updatedTotal);
3981     CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
3982 }
3983
3984 void testBranch()
3985 {
3986     Procedure proc;
3987     BasicBlock* root = proc.addBlock();
3988     BasicBlock* thenCase = proc.addBlock();
3989     BasicBlock* elseCase = proc.addBlock();
3990
3991     root->appendNew<ControlValue>(
3992         proc, Branch, Origin(),
3993         root->appendNew<Value>(
3994             proc, Trunc, Origin(),
3995             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3996         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
3997
3998     thenCase->appendNew<ControlValue>(
3999         proc, Return, Origin(),
4000         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
4001
4002     elseCase->appendNew<ControlValue>(
4003         proc, Return, Origin(),
4004         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
4005
4006     auto code = compile(proc);
4007     CHECK(invoke<int>(*code, 42) == 1);
4008     CHECK(invoke<int>(*code, 0) == 0);
4009 }
4010
4011 void testBranchPtr()
4012 {
4013     Procedure proc;
4014     BasicBlock* root = proc.addBlock();
4015     BasicBlock* thenCase = proc.addBlock();
4016     BasicBlock* elseCase = proc.addBlock();
4017
4018     root->appendNew<ControlValue>(
4019         proc, Branch, Origin(),
4020         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
4021         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
4022
4023     thenCase->appendNew<ControlValue>(
4024         proc, Return, Origin(),
4025         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
4026
4027     elseCase->appendNew<ControlValue>(
4028         proc, Return, Origin(),
4029         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
4030
4031     auto code = compile(proc);
4032     CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1);
4033     CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0);
4034 }
4035
4036 void testDiamond()
4037 {
4038     Procedure proc;
4039     BasicBlock* root = proc.addBlock();
4040     BasicBlock* thenCase = proc.addBlock();
4041     BasicBlock* elseCase = proc.addBlock();
4042     BasicBlock* done = proc.addBlock();
4043
4044     root->appendNew<ControlValue>(
4045         proc, Branch, Origin(),
4046         root->appendNew<Value>(
4047             proc, Trunc, Origin(),
4048             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
4049         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
4050