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