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