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