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