MacroAssembler needs an API for disabling scratch registers
[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 testDoubleArgToInt64BitwiseCast(double value)
1888 {
1889     Procedure proc;
1890     BasicBlock* root = proc.addBlock();
1891     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1892
1893     root->appendNew<ControlValue>(
1894         proc, Return, Origin(),
1895         root->appendNew<Value>(
1896             proc, BitwiseCast, Origin(), argument));
1897
1898     CHECK(isIdentical(compileAndRun<int64_t>(proc, value), bitwise_cast<int64_t>(value)));
1899 }
1900
1901 void testDoubleImmToInt64BitwiseCast(double value)
1902 {
1903     Procedure proc;
1904     BasicBlock* root = proc.addBlock();
1905     Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value);
1906
1907     root->appendNew<ControlValue>(
1908         proc, Return, Origin(),
1909         root->appendNew<Value>(
1910             proc, BitwiseCast, Origin(), argument));
1911
1912     CHECK(isIdentical(compileAndRun<int64_t>(proc), bitwise_cast<int64_t>(value)));
1913 }
1914
1915 void testTwoBitwiseCastOnDouble(double value)
1916 {
1917     Procedure proc;
1918     BasicBlock* root = proc.addBlock();
1919     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1920     Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
1921     Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
1922     root->appendNew<ControlValue>(proc, Return, Origin(), second);
1923
1924     CHECK(isIdentical(compileAndRun<double>(proc, value), value));
1925 }
1926
1927 void testBitwiseCastOnDoubleInMemory(double value)
1928 {
1929     Procedure proc;
1930     BasicBlock* root = proc.addBlock();
1931     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1932     MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
1933     Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
1934     root->appendNew<ControlValue>(proc, Return, Origin(), cast);
1935
1936     CHECK(isIdentical(compileAndRun<int64_t>(proc, &value), bitwise_cast<int64_t>(value)));
1937 }
1938
1939 void testInt64BArgToDoubleBitwiseCast(int64_t value)
1940 {
1941     Procedure proc;
1942     BasicBlock* root = proc.addBlock();
1943     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1944
1945     root->appendNew<ControlValue>(
1946         proc, Return, Origin(),
1947         root->appendNew<Value>(
1948             proc, BitwiseCast, Origin(), argument));
1949
1950     CHECK(isIdentical(compileAndRun<double>(proc, value), bitwise_cast<double>(value)));
1951 }
1952
1953 void testInt64BImmToDoubleBitwiseCast(int64_t value)
1954 {
1955     Procedure proc;
1956     BasicBlock* root = proc.addBlock();
1957     Value* argument = root->appendNew<Const64Value>(proc, Origin(), value);
1958
1959     root->appendNew<ControlValue>(
1960         proc, Return, Origin(),
1961         root->appendNew<Value>(
1962             proc, BitwiseCast, Origin(), argument));
1963
1964     CHECK(isIdentical(compileAndRun<double>(proc), bitwise_cast<double>(value)));
1965 }
1966
1967 void testTwoBitwiseCastOnInt64(int64_t value)
1968 {
1969     Procedure proc;
1970     BasicBlock* root = proc.addBlock();
1971     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1972     Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
1973     Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
1974     root->appendNew<ControlValue>(proc, Return, Origin(), second);
1975
1976     CHECK(isIdentical(compileAndRun<int64_t>(proc, value), value));
1977 }
1978
1979 void testBitwiseCastOnInt64InMemory(int64_t value)
1980 {
1981     Procedure proc;
1982     BasicBlock* root = proc.addBlock();
1983     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1984     MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1985     Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
1986     root->appendNew<ControlValue>(proc, Return, Origin(), cast);
1987
1988     CHECK(isIdentical(compileAndRun<double>(proc, &value), bitwise_cast<double>(value)));
1989 }
1990
1991 void testStore(int value)
1992 {
1993     Procedure proc;
1994     BasicBlock* root = proc.addBlock();
1995     int slot = 0xbaadbeef;
1996     root->appendNew<MemoryValue>(
1997         proc, Store, Origin(),
1998         root->appendNew<Value>(
1999             proc, Trunc, Origin(),
2000             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2001         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
2002     root->appendNew<ControlValue>(
2003         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2004
2005     CHECK(!compileAndRun<int>(proc, value));
2006     CHECK(slot == value);
2007 }
2008
2009 void testStoreConstant(int value)
2010 {
2011     Procedure proc;
2012     BasicBlock* root = proc.addBlock();
2013     int slot = 0xbaadbeef;
2014     root->appendNew<MemoryValue>(
2015         proc, Store, Origin(),
2016         root->appendNew<Const32Value>(proc, Origin(), value),
2017         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
2018     root->appendNew<ControlValue>(
2019         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2020
2021     CHECK(!compileAndRun<int>(proc));
2022     CHECK(slot == value);
2023 }
2024
2025 void testStoreConstantPtr(intptr_t value)
2026 {
2027     Procedure proc;
2028     BasicBlock* root = proc.addBlock();
2029     intptr_t slot;
2030     if (is64Bit())
2031         slot = (static_cast<intptr_t>(0xbaadbeef) << 32) + static_cast<intptr_t>(0xbaadbeef);
2032     else
2033         slot = 0xbaadbeef;
2034     root->appendNew<MemoryValue>(
2035         proc, Store, Origin(),
2036         root->appendNew<ConstPtrValue>(proc, Origin(), value),
2037         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
2038     root->appendNew<ControlValue>(
2039         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2040
2041     CHECK(!compileAndRun<int>(proc));
2042     CHECK(slot == value);
2043 }
2044
2045 void testTrunc(int64_t value)
2046 {
2047     Procedure proc;
2048     BasicBlock* root = proc.addBlock();
2049     root->appendNew<ControlValue>(
2050         proc, Return, Origin(),
2051         root->appendNew<Value>(
2052             proc, Trunc, Origin(),
2053             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2054
2055     CHECK(compileAndRun<int>(proc, value) == static_cast<int>(value));
2056 }
2057
2058 void testAdd1(int value)
2059 {
2060     Procedure proc;
2061     BasicBlock* root = proc.addBlock();
2062     root->appendNew<ControlValue>(
2063         proc, Return, Origin(),
2064         root->appendNew<Value>(
2065             proc, Add, Origin(),
2066             root->appendNew<Value>(
2067                 proc, Trunc, Origin(),
2068                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2069             root->appendNew<Const32Value>(proc, Origin(), 1)));
2070
2071     CHECK(compileAndRun<int>(proc, value) == value + 1);
2072 }
2073
2074 void testAdd1Ptr(intptr_t value)
2075 {
2076     Procedure proc;
2077     BasicBlock* root = proc.addBlock();
2078     root->appendNew<ControlValue>(
2079         proc, Return, Origin(),
2080         root->appendNew<Value>(
2081             proc, Add, Origin(),
2082             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2083             root->appendNew<ConstPtrValue>(proc, Origin(), 1)));
2084
2085     CHECK(compileAndRun<intptr_t>(proc, value) == value + 1);
2086 }
2087
2088 void testNeg32(int32_t value)
2089 {
2090     Procedure proc;
2091     BasicBlock* root = proc.addBlock();
2092     root->appendNew<ControlValue>(
2093         proc, Return, Origin(),
2094         root->appendNew<Value>(
2095             proc, Sub, Origin(),
2096             root->appendNew<Const32Value>(proc, Origin(), 0),
2097             root->appendNew<Value>(
2098                 proc, Trunc, Origin(),
2099                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2100
2101     CHECK(compileAndRun<int32_t>(proc, value) == -value);
2102 }
2103
2104 void testNegPtr(intptr_t value)
2105 {
2106     Procedure proc;
2107     BasicBlock* root = proc.addBlock();
2108     root->appendNew<ControlValue>(
2109         proc, Return, Origin(),
2110         root->appendNew<Value>(
2111             proc, Sub, Origin(),
2112             root->appendNew<ConstPtrValue>(proc, Origin(), 0),
2113             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2114
2115     CHECK(compileAndRun<intptr_t>(proc, value) == -value);
2116 }
2117
2118 void testStoreAddLoad(int amount)
2119 {
2120     Procedure proc;
2121     BasicBlock* root = proc.addBlock();
2122     int slot = 37;
2123     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
2124     root->appendNew<MemoryValue>(
2125         proc, Store, Origin(),
2126         root->appendNew<Value>(
2127             proc, Add, Origin(),
2128             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
2129             root->appendNew<Const32Value>(proc, Origin(), amount)),
2130         slotPtr);
2131     root->appendNew<ControlValue>(
2132         proc, Return, Origin(),
2133         root->appendNew<Const32Value>(proc, Origin(), 0));
2134
2135     CHECK(!compileAndRun<int>(proc));
2136     CHECK(slot == 37 + amount);
2137 }
2138
2139 void testStoreSubLoad(int amount)
2140 {
2141     Procedure proc;
2142     BasicBlock* root = proc.addBlock();
2143     int32_t startValue = std::numeric_limits<int32_t>::min();
2144     int32_t slot = startValue;
2145     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
2146     root->appendNew<MemoryValue>(
2147         proc, Store, Origin(),
2148         root->appendNew<Value>(
2149             proc, Sub, Origin(),
2150             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
2151             root->appendNew<Value>(
2152                 proc, Trunc, Origin(),
2153                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
2154         slotPtr);
2155     root->appendNew<ControlValue>(
2156         proc, Return, Origin(),
2157         root->appendNew<Const32Value>(proc, Origin(), 0));
2158
2159     CHECK(!compileAndRun<int>(proc, amount));
2160     CHECK(slot == startValue - amount);
2161 }
2162
2163 void testStoreAddLoadInterference(int amount)
2164 {
2165     Procedure proc;
2166     BasicBlock* root = proc.addBlock();
2167     int slot = 37;
2168     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
2169     ArgumentRegValue* otherSlotPtr =
2170         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2171     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr);
2172     root->appendNew<MemoryValue>(
2173         proc, Store, Origin(),
2174         root->appendNew<Const32Value>(proc, Origin(), 666),
2175         otherSlotPtr);
2176     root->appendNew<MemoryValue>(
2177         proc, Store, Origin(),
2178         root->appendNew<Value>(
2179             proc, Add, Origin(),
2180             load, root->appendNew<Const32Value>(proc, Origin(), amount)),
2181         slotPtr);
2182     root->appendNew<ControlValue>(
2183         proc, Return, Origin(),
2184         root->appendNew<Const32Value>(proc, Origin(), 0));
2185
2186     CHECK(!compileAndRun<int>(proc, &slot));
2187     CHECK(slot == 37 + amount);
2188 }
2189
2190 void testStoreAddAndLoad(int amount, int mask)
2191 {
2192     Procedure proc;
2193     BasicBlock* root = proc.addBlock();
2194     int slot = 37;
2195     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
2196     root->appendNew<MemoryValue>(
2197         proc, Store, Origin(),
2198         root->appendNew<Value>(
2199             proc, BitAnd, Origin(),
2200             root->appendNew<Value>(
2201                 proc, Add, Origin(),
2202                 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
2203                 root->appendNew<Const32Value>(proc, Origin(), amount)),
2204             root->appendNew<Const32Value>(proc, Origin(), mask)),
2205         slotPtr);
2206     root->appendNew<ControlValue>(
2207         proc, Return, Origin(),
2208         root->appendNew<Const32Value>(proc, Origin(), 0));
2209
2210     CHECK(!compileAndRun<int>(proc));
2211     CHECK(slot == ((37 + amount) & mask));
2212 }
2213
2214 void testStoreNegLoad32(int32_t value)
2215 {
2216     Procedure proc;
2217     BasicBlock* root = proc.addBlock();
2218
2219     int32_t slot = value;
2220
2221     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
2222     
2223     root->appendNew<MemoryValue>(
2224         proc, Store, Origin(),
2225         root->appendNew<Value>(
2226             proc, Sub, Origin(),
2227             root->appendNew<Const32Value>(proc, Origin(), 0),
2228             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)),
2229         slotPtr);
2230     
2231     root->appendNew<ControlValue>(
2232         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2233
2234     CHECK(!compileAndRun<int32_t>(proc));
2235     CHECK(slot == -value);
2236 }
2237
2238 void testStoreNegLoadPtr(intptr_t value)
2239 {
2240     Procedure proc;
2241     BasicBlock* root = proc.addBlock();
2242
2243     intptr_t slot = value;
2244
2245     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
2246     
2247     root->appendNew<MemoryValue>(
2248         proc, Store, Origin(),
2249         root->appendNew<Value>(
2250             proc, Sub, Origin(),
2251             root->appendNew<ConstPtrValue>(proc, Origin(), 0),
2252             root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)),
2253         slotPtr);
2254     
2255     root->appendNew<ControlValue>(
2256         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2257
2258     CHECK(!compileAndRun<int32_t>(proc));
2259     CHECK(slot == -value);
2260 }
2261
2262 void testAdd1Uncommuted(int value)
2263 {
2264     Procedure proc;
2265     BasicBlock* root = proc.addBlock();
2266     root->appendNew<ControlValue>(
2267         proc, Return, Origin(),
2268         root->appendNew<Value>(
2269             proc, Add, Origin(),
2270             root->appendNew<Const32Value>(proc, Origin(), 1),
2271             root->appendNew<Value>(
2272                 proc, Trunc, Origin(),
2273                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2274
2275     CHECK(compileAndRun<int>(proc, value) == value + 1);
2276 }
2277
2278 void testLoadOffset()
2279 {
2280     Procedure proc;
2281     BasicBlock* root = proc.addBlock();
2282     int array[] = { 1, 2 };
2283     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
2284     root->appendNew<ControlValue>(
2285         proc, Return, Origin(),
2286         root->appendNew<Value>(
2287             proc, Add, Origin(),
2288             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
2289             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int))));
2290
2291     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
2292 }
2293
2294 void testLoadOffsetNotConstant()
2295 {
2296     Procedure proc;
2297     BasicBlock* root = proc.addBlock();
2298     int array[] = { 1, 2 };
2299     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2300     root->appendNew<ControlValue>(
2301         proc, Return, Origin(),
2302         root->appendNew<Value>(
2303             proc, Add, Origin(),
2304             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
2305             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int))));
2306
2307     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
2308 }
2309
2310 void testLoadOffsetUsingAdd()
2311 {
2312     Procedure proc;
2313     BasicBlock* root = proc.addBlock();
2314     int array[] = { 1, 2 };
2315     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
2316     root->appendNew<ControlValue>(
2317         proc, Return, Origin(),
2318         root->appendNew<Value>(
2319             proc, Add, Origin(),
2320             root->appendNew<MemoryValue>(
2321                 proc, Load, Int32, Origin(),
2322                 root->appendNew<Value>(
2323                     proc, Add, Origin(), arrayPtr,
2324                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
2325             root->appendNew<MemoryValue>(
2326                 proc, Load, Int32, Origin(),
2327                 root->appendNew<Value>(
2328                     proc, Add, Origin(), arrayPtr,
2329                     root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
2330     
2331     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
2332 }
2333
2334 void testLoadOffsetUsingAddInterference()
2335 {
2336     Procedure proc;
2337     BasicBlock* root = proc.addBlock();
2338     int array[] = { 1, 2 };
2339     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
2340     ArgumentRegValue* otherArrayPtr =
2341         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2342     Const32Value* theNumberOfTheBeast = root->appendNew<Const32Value>(proc, Origin(), 666);
2343     MemoryValue* left = root->appendNew<MemoryValue>(
2344         proc, Load, Int32, Origin(),
2345         root->appendNew<Value>(
2346             proc, Add, Origin(), arrayPtr,
2347             root->appendNew<ConstPtrValue>(proc, Origin(), 0)));
2348     MemoryValue* right = root->appendNew<MemoryValue>(
2349         proc, Load, Int32, Origin(),
2350         root->appendNew<Value>(
2351             proc, Add, Origin(), arrayPtr,
2352             root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))));
2353     root->appendNew<MemoryValue>(
2354         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0);
2355     root->appendNew<MemoryValue>(
2356         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, sizeof(int));
2357     root->appendNew<ControlValue>(
2358         proc, Return, Origin(),
2359         root->appendNew<Value>(
2360             proc, Add, Origin(), left, right));
2361     
2362     CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2);
2363     CHECK(array[0] == 666);
2364     CHECK(array[1] == 666);
2365 }
2366
2367 void testLoadOffsetUsingAddNotConstant()
2368 {
2369     Procedure proc;
2370     BasicBlock* root = proc.addBlock();
2371     int array[] = { 1, 2 };
2372     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2373     root->appendNew<ControlValue>(
2374         proc, Return, Origin(),
2375         root->appendNew<Value>(
2376             proc, Add, Origin(),
2377             root->appendNew<MemoryValue>(
2378                 proc, Load, Int32, Origin(),
2379                 root->appendNew<Value>(
2380                     proc, Add, Origin(), arrayPtr,
2381                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
2382             root->appendNew<MemoryValue>(
2383                 proc, Load, Int32, Origin(),
2384                 root->appendNew<Value>(
2385                     proc, Add, Origin(), arrayPtr,
2386                     root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
2387     
2388     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
2389 }
2390
2391 void testLoadAddrShift(unsigned shift)
2392 {
2393     Procedure proc;
2394     BasicBlock* root = proc.addBlock();
2395     int slots[2];
2396
2397     // Figure out which slot to use while having proper alignment for the shift.
2398     int* slot;
2399     uintptr_t arg;
2400     for (unsigned i = sizeof(slots)/sizeof(slots[0]); i--;) {
2401         slot = slots + i;
2402         arg = bitwise_cast<uintptr_t>(slot) >> shift;
2403         if (bitwise_cast<int*>(arg << shift) == slot)
2404             break;
2405     }
2406
2407     *slot = 8675309;
2408     
2409     root->appendNew<ControlValue>(
2410         proc, Return, Origin(),
2411         root->appendNew<MemoryValue>(
2412             proc, Load, Int32, Origin(),
2413             root->appendNew<Value>(
2414                 proc, Shl, Origin(),
2415                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2416                 root->appendNew<Const32Value>(proc, Origin(), shift))));
2417
2418     CHECK(compileAndRun<int>(proc, arg) == 8675309);
2419 }
2420
2421 void testFramePointer()
2422 {
2423     Procedure proc;
2424     BasicBlock* root = proc.addBlock();
2425     root->appendNew<ControlValue>(
2426         proc, Return, Origin(),
2427         root->appendNew<Value>(proc, FramePointer, Origin()));
2428
2429     void* fp = compileAndRun<void*>(proc);
2430     CHECK(fp < &proc);
2431     CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
2432 }
2433
2434 void testStackSlot()
2435 {
2436     Procedure proc;
2437     BasicBlock* root = proc.addBlock();
2438     root->appendNew<ControlValue>(
2439         proc, Return, Origin(),
2440         root->appendNew<StackSlotValue>(proc, Origin(), 1, StackSlotKind::Anonymous));
2441
2442     void* stackSlot = compileAndRun<void*>(proc);
2443     CHECK(stackSlot < &proc);
2444     CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000);
2445 }
2446
2447 void testLoadFromFramePointer()
2448 {
2449     Procedure proc;
2450     BasicBlock* root = proc.addBlock();
2451     root->appendNew<ControlValue>(
2452         proc, Return, Origin(),
2453         root->appendNew<MemoryValue>(
2454             proc, Load, pointerType(), Origin(),
2455             root->appendNew<Value>(proc, FramePointer, Origin())));
2456
2457     void* fp = compileAndRun<void*>(proc);
2458     void* myFP = __builtin_frame_address(0);
2459     CHECK(fp <= myFP);
2460     CHECK(fp >= bitwise_cast<char*>(myFP) - 10000);
2461 }
2462
2463 void testStoreLoadStackSlot(int value)
2464 {
2465     Procedure proc;
2466     BasicBlock* root = proc.addBlock();
2467
2468     StackSlotValue* stack = root->appendNew<StackSlotValue>(
2469         proc, Origin(), sizeof(int), StackSlotKind::Anonymous);
2470
2471     root->appendNew<MemoryValue>(
2472         proc, Store, Origin(),
2473         root->appendNew<Value>(
2474             proc, Trunc, Origin(),
2475             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2476         stack);
2477     
2478     root->appendNew<ControlValue>(
2479         proc, Return, Origin(),
2480         root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack));
2481
2482     CHECK(compileAndRun<int>(proc, value) == value);
2483 }
2484
2485 template<typename T>
2486 int32_t modelLoad(int32_t value)
2487 {
2488     union {
2489         int32_t original;
2490         T loaded;
2491     } u;
2492
2493     u.original = value;
2494     if (std::is_signed<T>::value)
2495         return static_cast<int32_t>(u.loaded);
2496     return static_cast<int32_t>(static_cast<uint32_t>(u.loaded));
2497 }
2498
2499 template<typename T>
2500 void testLoad(B3::Opcode opcode, int32_t value)
2501 {
2502     // Simple load from an absolute address.
2503     {
2504         Procedure proc;
2505         BasicBlock* root = proc.addBlock();
2506         
2507         root->appendNew<ControlValue>(
2508             proc, Return, Origin(),
2509             root->appendNew<MemoryValue>(
2510                 proc, opcode, Int32, Origin(),
2511                 root->appendNew<ConstPtrValue>(proc, Origin(), &value)));
2512
2513         CHECK(compileAndRun<int32_t>(proc) == modelLoad<T>(value));
2514     }
2515     
2516     // Simple load from an address in a register.
2517     {
2518         Procedure proc;
2519         BasicBlock* root = proc.addBlock();
2520         
2521         root->appendNew<ControlValue>(
2522             proc, Return, Origin(),
2523             root->appendNew<MemoryValue>(
2524                 proc, opcode, Int32, Origin(),
2525                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2526
2527         CHECK(compileAndRun<int32_t>(proc, &value) == modelLoad<T>(value));
2528     }
2529     
2530     // Simple load from an address in a register, at an offset.
2531     {
2532         Procedure proc;
2533         BasicBlock* root = proc.addBlock();
2534         
2535         root->appendNew<ControlValue>(
2536             proc, Return, Origin(),
2537             root->appendNew<MemoryValue>(
2538                 proc, opcode, Int32, Origin(),
2539                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2540                 sizeof(int32_t)));
2541
2542         CHECK(compileAndRun<int32_t>(proc, &value - 1) == modelLoad<T>(value));
2543     }
2544
2545     // Load from a simple base-index with various scales.
2546     for (unsigned logScale = 0; logScale <= 3; ++logScale) {
2547         Procedure proc;
2548         BasicBlock* root = proc.addBlock();
2549
2550         root->appendNew<ControlValue>(
2551             proc, Return, Origin(),
2552             root->appendNew<MemoryValue>(
2553                 proc, opcode, Int32, Origin(),
2554                 root->appendNew<Value>(
2555                     proc, Add, Origin(),
2556                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2557                     root->appendNew<Value>(
2558                         proc, Shl, Origin(),
2559                         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
2560                         root->appendNew<Const32Value>(proc, Origin(), logScale)))));
2561
2562         CHECK(compileAndRun<int32_t>(proc, &value - 2, (sizeof(int32_t) * 2) >> logScale) == modelLoad<T>(value));
2563     }
2564
2565     // Load from a simple base-index with various scales, but commuted.
2566     for (unsigned logScale = 0; logScale <= 3; ++logScale) {
2567         Procedure proc;
2568         BasicBlock* root = proc.addBlock();
2569
2570         root->appendNew<ControlValue>(
2571             proc, Return, Origin(),
2572             root->appendNew<MemoryValue>(
2573                 proc, opcode, Int32, Origin(),
2574                 root->appendNew<Value>(
2575                     proc, Add, Origin(),
2576                     root->appendNew<Value>(
2577                         proc, Shl, Origin(),
2578                         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
2579                         root->appendNew<Const32Value>(proc, Origin(), logScale)),
2580                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2581
2582         CHECK(compileAndRun<int32_t>(proc, &value - 2, (sizeof(int32_t) * 2) >> logScale) == modelLoad<T>(value));
2583     }
2584 }
2585
2586 void testSpillGP()
2587 {
2588     Procedure proc;
2589     BasicBlock* root = proc.addBlock();
2590
2591     Vector<Value*> sources;
2592     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2593     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2594
2595     for (unsigned i = 0; i < 30; ++i) {
2596         sources.append(
2597             root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
2598         );
2599     }
2600
2601     Value* total = root->appendNew<Const64Value>(proc, Origin(), 0);
2602     for (Value* value : sources)
2603         total = root->appendNew<Value>(proc, Add, Origin(), total, value);
2604
2605     root->appendNew<ControlValue>(proc, Return, Origin(), total);
2606     compileAndRun<int>(proc, 1, 2);
2607 }
2608
2609 void testSpillFP()
2610 {
2611     Procedure proc;
2612     BasicBlock* root = proc.addBlock();
2613
2614     Vector<Value*> sources;
2615     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
2616     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
2617
2618     for (unsigned i = 0; i < 30; ++i) {
2619         sources.append(
2620             root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
2621         );
2622     }
2623
2624     Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
2625     for (Value* value : sources)
2626         total = root->appendNew<Value>(proc, Add, Origin(), total, value);
2627
2628     root->appendNew<ControlValue>(proc, Return, Origin(), total);
2629     compileAndRun<double>(proc, 1.1, 2.5);
2630 }
2631
2632 void testBranch()
2633 {
2634     Procedure proc;
2635     BasicBlock* root = proc.addBlock();
2636     BasicBlock* thenCase = proc.addBlock();
2637     BasicBlock* elseCase = proc.addBlock();
2638
2639     root->appendNew<ControlValue>(
2640         proc, Branch, Origin(),
2641         root->appendNew<Value>(
2642             proc, Trunc, Origin(),
2643             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2644         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2645
2646     thenCase->appendNew<ControlValue>(
2647         proc, Return, Origin(),
2648         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2649
2650     elseCase->appendNew<ControlValue>(
2651         proc, Return, Origin(),
2652         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2653
2654     auto code = compile(proc);
2655     CHECK(invoke<int>(*code, 42) == 1);
2656     CHECK(invoke<int>(*code, 0) == 0);
2657 }
2658
2659 void testBranchPtr()
2660 {
2661     Procedure proc;
2662     BasicBlock* root = proc.addBlock();
2663     BasicBlock* thenCase = proc.addBlock();
2664     BasicBlock* elseCase = proc.addBlock();
2665
2666     root->appendNew<ControlValue>(
2667         proc, Branch, Origin(),
2668         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2669         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2670
2671     thenCase->appendNew<ControlValue>(
2672         proc, Return, Origin(),
2673         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2674
2675     elseCase->appendNew<ControlValue>(
2676         proc, Return, Origin(),
2677         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2678
2679     auto code = compile(proc);
2680     CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1);
2681     CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0);
2682 }
2683
2684 void testDiamond()
2685 {
2686     Procedure proc;
2687     BasicBlock* root = proc.addBlock();
2688     BasicBlock* thenCase = proc.addBlock();
2689     BasicBlock* elseCase = proc.addBlock();
2690     BasicBlock* done = proc.addBlock();
2691
2692     root->appendNew<ControlValue>(
2693         proc, Branch, Origin(),
2694         root->appendNew<Value>(
2695             proc, Trunc, Origin(),
2696             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2697         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2698
2699     UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
2700         proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2701     thenCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
2702
2703     UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
2704         proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2705     elseCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
2706
2707     Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
2708     thenResult->setPhi(phi);
2709     elseResult->setPhi(phi);
2710     done->appendNew<ControlValue>(proc, Return, Origin(), phi);
2711
2712     auto code = compile(proc);
2713     CHECK(invoke<int>(*code, 42) == 1);
2714     CHECK(invoke<int>(*code, 0) == 0);
2715 }
2716
2717 void testBranchNotEqual()
2718 {
2719     Procedure proc;
2720     BasicBlock* root = proc.addBlock();
2721     BasicBlock* thenCase = proc.addBlock();
2722     BasicBlock* elseCase = proc.addBlock();
2723
2724     root->appendNew<ControlValue>(
2725         proc, Branch, Origin(),
2726         root->appendNew<Value>(
2727             proc, NotEqual, Origin(),
2728             root->appendNew<Value>(
2729                 proc, Trunc, Origin(),
2730                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2731             root->appendNew<Const32Value>(proc, Origin(), 0)),
2732         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2733
2734     thenCase->appendNew<ControlValue>(
2735         proc, Return, Origin(),
2736         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2737
2738     elseCase->appendNew<ControlValue>(
2739         proc, Return, Origin(),
2740         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2741
2742     auto code = compile(proc);
2743     CHECK(invoke<int>(*code, 42) == 1);
2744     CHECK(invoke<int>(*code, 0) == 0);
2745 }
2746
2747 void testBranchNotEqualCommute()
2748 {
2749     Procedure proc;
2750     BasicBlock* root = proc.addBlock();
2751     BasicBlock* thenCase = proc.addBlock();
2752     BasicBlock* elseCase = proc.addBlock();
2753
2754     root->appendNew<ControlValue>(
2755         proc, Branch, Origin(),
2756         root->appendNew<Value>(
2757             proc, NotEqual, Origin(),
2758             root->appendNew<Const32Value>(proc, Origin(), 0),
2759             root->appendNew<Value>(
2760                 proc, Trunc, Origin(),
2761                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
2762         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2763
2764     thenCase->appendNew<ControlValue>(
2765         proc, Return, Origin(),
2766         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2767
2768     elseCase->appendNew<ControlValue>(
2769         proc, Return, Origin(),
2770         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2771
2772     auto code = compile(proc);
2773     CHECK(invoke<int>(*code, 42) == 1);
2774     CHECK(invoke<int>(*code, 0) == 0);
2775 }
2776
2777 void testBranchNotEqualNotEqual()
2778 {
2779     Procedure proc;
2780     BasicBlock* root = proc.addBlock();
2781     BasicBlock* thenCase = proc.addBlock();
2782     BasicBlock* elseCase = proc.addBlock();
2783
2784     root->appendNew<ControlValue>(
2785         proc, Branch, Origin(),
2786         root->appendNew<Value>(
2787             proc, NotEqual, Origin(),
2788             root->appendNew<Value>(
2789                 proc, NotEqual, Origin(),
2790                 root->appendNew<Value>(
2791                     proc, Trunc, Origin(),
2792                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2793                 root->appendNew<Const32Value>(proc, Origin(), 0)),
2794             root->appendNew<Const32Value>(proc, Origin(), 0)),
2795         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2796
2797     thenCase->appendNew<ControlValue>(
2798         proc, Return, Origin(),
2799         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2800
2801     elseCase->appendNew<ControlValue>(
2802         proc, Return, Origin(),
2803         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2804
2805     auto code = compile(proc);
2806     CHECK(invoke<int>(*code, 42) == 1);
2807     CHECK(invoke<int>(*code, 0) == 0);
2808 }
2809
2810 void testBranchEqual()
2811 {
2812     Procedure proc;
2813     BasicBlock* root = proc.addBlock();
2814     BasicBlock* thenCase = proc.addBlock();
2815     BasicBlock* elseCase = proc.addBlock();
2816
2817     root->appendNew<ControlValue>(
2818         proc, Branch, Origin(),
2819         root->appendNew<Value>(
2820             proc, Equal, Origin(),
2821             root->appendNew<Value>(
2822                 proc, Trunc, Origin(),
2823                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2824             root->appendNew<Const32Value>(proc, Origin(), 0)),
2825         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2826
2827     thenCase->appendNew<ControlValue>(
2828         proc, Return, Origin(),
2829         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
2830
2831     elseCase->appendNew<ControlValue>(
2832         proc, Return, Origin(),
2833         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
2834
2835     auto code = compile(proc);
2836     CHECK(invoke<int>(*code, 42) == 1);
2837     CHECK(invoke<int>(*code, 0) == 0);
2838 }
2839
2840 void testBranchEqualEqual()
2841 {
2842     Procedure proc;
2843     BasicBlock* root = proc.addBlock();
2844     BasicBlock* thenCase = proc.addBlock();
2845     BasicBlock* elseCase = proc.addBlock();
2846
2847     root->appendNew<ControlValue>(
2848         proc, Branch, Origin(),
2849         root->appendNew<Value>(
2850             proc, Equal, Origin(),
2851             root->appendNew<Value>(
2852                 proc, Equal, Origin(),
2853                 root->appendNew<Value>(
2854                     proc, Trunc, Origin(),
2855                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2856                 root->appendNew<Const32Value>(proc, Origin(), 0)),
2857             root->appendNew<Const32Value>(proc, Origin(), 0)),
2858         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2859
2860     thenCase->appendNew<ControlValue>(
2861         proc, Return, Origin(),
2862         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2863
2864     elseCase->appendNew<ControlValue>(
2865         proc, Return, Origin(),
2866         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2867
2868     auto code = compile(proc);
2869     CHECK(invoke<int>(*code, 42) == 1);
2870     CHECK(invoke<int>(*code, 0) == 0);
2871 }
2872
2873 void testBranchEqualCommute()
2874 {
2875     Procedure proc;
2876     BasicBlock* root = proc.addBlock();
2877     BasicBlock* thenCase = proc.addBlock();
2878     BasicBlock* elseCase = proc.addBlock();
2879
2880     root->appendNew<ControlValue>(
2881         proc, Branch, Origin(),
2882         root->appendNew<Value>(
2883             proc, Equal, Origin(),
2884             root->appendNew<Const32Value>(proc, Origin(), 0),
2885             root->appendNew<Value>(
2886                 proc, Trunc, Origin(),
2887                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
2888         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2889
2890     thenCase->appendNew<ControlValue>(
2891         proc, Return, Origin(),
2892         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
2893
2894     elseCase->appendNew<ControlValue>(
2895         proc, Return, Origin(),
2896         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
2897
2898     auto code = compile(proc);
2899     CHECK(invoke<int>(*code, 42) == 1);
2900     CHECK(invoke<int>(*code, 0) == 0);
2901 }
2902
2903 void testBranchEqualEqual1()
2904 {
2905     Procedure proc;
2906     BasicBlock* root = proc.addBlock();
2907     BasicBlock* thenCase = proc.addBlock();
2908     BasicBlock* elseCase = proc.addBlock();
2909
2910     root->appendNew<ControlValue>(
2911         proc, Branch, Origin(),
2912         root->appendNew<Value>(
2913             proc, Equal, Origin(),
2914             root->appendNew<Value>(
2915                 proc, Equal, Origin(),
2916                 root->appendNew<Value>(
2917                     proc, Trunc, Origin(),
2918                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2919                 root->appendNew<Const32Value>(proc, Origin(), 0)),
2920             root->appendNew<Const32Value>(proc, Origin(), 1)),
2921         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2922
2923     thenCase->appendNew<ControlValue>(
2924         proc, Return, Origin(),
2925         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
2926
2927     elseCase->appendNew<ControlValue>(
2928         proc, Return, Origin(),
2929         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
2930
2931     auto code = compile(proc);
2932     CHECK(invoke<int>(*code, 42) == 1);
2933     CHECK(invoke<int>(*code, 0) == 0);
2934 }
2935
2936 void testBranchFold(int value)
2937 {
2938     Procedure proc;
2939     BasicBlock* root = proc.addBlock();
2940     BasicBlock* thenCase = proc.addBlock();
2941     BasicBlock* elseCase = proc.addBlock();
2942
2943     root->appendNew<ControlValue>(
2944         proc, Branch, Origin(),
2945         root->appendNew<Const32Value>(proc, Origin(), value),
2946         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2947
2948     thenCase->appendNew<ControlValue>(
2949         proc, Return, Origin(),
2950         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2951
2952     elseCase->appendNew<ControlValue>(
2953         proc, Return, Origin(),
2954         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2955
2956     CHECK(compileAndRun<int>(proc) == !!value);
2957 }
2958
2959 void testDiamondFold(int value)
2960 {
2961     Procedure proc;
2962     BasicBlock* root = proc.addBlock();
2963     BasicBlock* thenCase = proc.addBlock();
2964     BasicBlock* elseCase = proc.addBlock();
2965     BasicBlock* done = proc.addBlock();
2966
2967     root->appendNew<ControlValue>(
2968         proc, Branch, Origin(),
2969         root->appendNew<Const32Value>(proc, Origin(), value),
2970         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2971
2972     UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
2973         proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2974     thenCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
2975
2976     UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
2977         proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2978     elseCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
2979
2980     Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
2981     thenResult->setPhi(phi);
2982     elseResult->setPhi(phi);
2983     done->appendNew<ControlValue>(proc, Return, Origin(), phi);
2984
2985     CHECK(compileAndRun<int>(proc) == !!value);
2986 }
2987
2988 void testBranchNotEqualFoldPtr(intptr_t value)
2989 {
2990     Procedure proc;
2991     BasicBlock* root = proc.addBlock();
2992     BasicBlock* thenCase = proc.addBlock();
2993     BasicBlock* elseCase = proc.addBlock();
2994
2995     root->appendNew<ControlValue>(
2996         proc, Branch, Origin(),
2997         root->appendNew<Value>(
2998             proc, NotEqual, Origin(),
2999             root->appendNew<ConstPtrValue>(proc, Origin(), value),
3000             root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
3001         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
3002
3003     thenCase->appendNew<ControlValue>(
3004         proc, Return, Origin(),
3005         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
3006
3007     elseCase->appendNew<ControlValue>(
3008         proc, Return, Origin(),
3009         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
3010
3011     CHECK(compileAndRun<int>(proc) == !!value);
3012 }
3013
3014 void testBranchEqualFoldPtr(intptr_t value)
3015 {
3016     Procedure proc;
3017     BasicBlock* root = proc.addBlock();
3018     BasicBlock* thenCase = proc.addBlock();
3019     BasicBlock* elseCase = proc.addBlock();
3020
3021     root->appendNew<ControlValue>(
3022         proc, Branch, Origin(),
3023         root->appendNew<Value>(
3024             proc, Equal, Origin(),
3025             root->appendNew<ConstPtrValue>(proc, Origin(), value),
3026             root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
3027         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
3028
3029     thenCase->appendNew<ControlValue>(
3030         proc, Return, Origin(),
3031         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
3032
3033     elseCase->appendNew<ControlValue>(
3034         proc, Return, Origin(),
3035         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
3036
3037     CHECK(compileAndRun<int>(proc) == !value);
3038 }
3039
3040 void testComplex(unsigned numVars, unsigned numConstructs)
3041 {
3042     double before = monotonicallyIncreasingTimeMS();
3043     
3044     Procedure proc;
3045     BasicBlock* current = proc.addBlock();
3046
3047     Const32Value* one = current->appendNew<Const32Value>(proc, Origin(), 1);
3048
3049     Vector<int32_t> varSlots;
3050     for (unsigned i = numVars; i--;)
3051         varSlots.append(i);
3052
3053     Vector<Value*> vars;
3054     for (int32_t& varSlot : varSlots) {
3055         Value* varSlotPtr = current->appendNew<ConstPtrValue>(proc, Origin(), &varSlot);
3056         vars.append(current->appendNew<MemoryValue>(proc, Load, Int32, Origin(), varSlotPtr));
3057     }
3058
3059     for (unsigned i = 0; i < numConstructs; ++i) {
3060         if (i & 1) {
3061             // Control flow diamond.
3062             unsigned predicateVarIndex = ((i >> 1) + 2) % numVars;
3063             unsigned thenIncVarIndex = ((i >> 1) + 0) % numVars;
3064             unsigned elseIncVarIndex = ((i >> 1) + 1) % numVars;
3065
3066             BasicBlock* thenBlock = proc.addBlock();
3067             BasicBlock* elseBlock = proc.addBlock();
3068             BasicBlock* continuation = proc.addBlock();
3069
3070             current->appendNew<ControlValue>(
3071                 proc, Branch, Origin(), vars[predicateVarIndex],
3072                 FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
3073
3074             UpsilonValue* thenThenResult = thenBlock->appendNew<UpsilonValue>(
3075                 proc, Origin(),
3076                 thenBlock->appendNew<Value>(proc, Add, Origin(), vars[thenIncVarIndex], one));
3077             UpsilonValue* thenElseResult = thenBlock->appendNew<UpsilonValue>(
3078                 proc, Origin(), vars[elseIncVarIndex]);
3079             thenBlock->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
3080
3081             UpsilonValue* elseElseResult = elseBlock->appendNew<UpsilonValue>(
3082                 proc, Origin(),
3083                 elseBlock->appendNew<Value>(proc, Add, Origin(), vars[elseIncVarIndex], one));
3084             UpsilonValue* elseThenResult = elseBlock->appendNew<UpsilonValue>(
3085                 proc, Origin(), vars[thenIncVarIndex]);
3086             elseBlock->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
3087
3088             Value* thenPhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
3089             thenThenResult->setPhi(thenPhi);
3090             elseThenResult->setPhi(thenPhi);
3091             vars[thenIncVarIndex] = thenPhi;
3092             
3093             Value* elsePhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
3094             thenElseResult->setPhi(elsePhi);
3095             elseElseResult->setPhi(elsePhi);
3096             vars[elseIncVarIndex] = thenPhi;
3097             
3098             current = continuation;
3099         } else {
3100             // Loop.
3101
3102             BasicBlock* loopEntry = proc.addBlock();
3103             BasicBlock* loopReentry = proc.addBlock();
3104             BasicBlock* loopBody = proc.addBlock();
3105             BasicBlock* loopExit = proc.addBlock();
3106             BasicBlock* loopSkip = proc.addBlock();
3107             BasicBlock* continuation = proc.addBlock();
3108             
3109             Value* startIndex = vars[((i >> 1) + 1) % numVars];
3110             Value* startSum = current->appendNew<Const32Value>(proc, Origin(), 0);
3111             current->appendNew<ControlValue>(
3112                 proc, Branch, Origin(), startIndex,
3113                 FrequentedBlock(loopEntry), FrequentedBlock(loopSkip));
3114
3115             UpsilonValue* startIndexForBody = loopEntry->appendNew<UpsilonValue>(
3116                 proc, Origin(), startIndex);
3117             UpsilonValue* startSumForBody = loopEntry->appendNew<UpsilonValue>(
3118                 proc, Origin(), startSum);
3119             loopEntry->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loopBody));
3120
3121             Value* bodyIndex = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
3122             startIndexForBody->setPhi(bodyIndex);
3123             Value* bodySum = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
3124             startSumForBody->setPhi(bodySum);
3125             Value* newBodyIndex = loopBody->appendNew<Value>(proc, Sub, Origin(), bodyIndex, one);
3126             Value* newBodySum = loopBody->appendNew<Value>(
3127                 proc, Add, Origin(),
3128                 bodySum,
3129                 loopBody->appendNew<MemoryValue>(
3130                     proc, Load, Int32, Origin(),
3131                     loopBody->appendNew<Value>(
3132                         proc, Add, Origin(),
3133                         loopBody->appendNew<ConstPtrValue>(proc, Origin(), varSlots.data()),
3134                         loopBody->appendNew<Value>(
3135                             proc, Shl, Origin(),
3136                             loopBody->appendNew<Value>(
3137                                 proc, ZExt32, Origin(),
3138                                 loopBody->appendNew<Value>(
3139                                     proc, BitAnd, Origin(),
3140                                     newBodyIndex,
3141                                     loopBody->appendNew<Const32Value>(
3142                                         proc, Origin(), numVars - 1))),
3143                             loopBody->appendNew<Const32Value>(proc, Origin(), 2)))));
3144             loopBody->appendNew<ControlValue>(
3145                 proc, Branch, Origin(), newBodyIndex,
3146                 FrequentedBlock(loopReentry), FrequentedBlock(loopExit));
3147
3148             loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodyIndex, bodyIndex);
3149             loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodySum, bodySum);
3150             loopReentry->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loopBody));
3151
3152             UpsilonValue* exitSum = loopExit->appendNew<UpsilonValue>(proc, Origin(), newBodySum);
3153             loopExit->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
3154
3155             UpsilonValue* skipSum = loopSkip->appendNew<UpsilonValue>(proc, Origin(), startSum);
3156             loopSkip->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
3157
3158             Value* finalSum = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
3159             exitSum->setPhi(finalSum);
3160             skipSum->setPhi(finalSum);
3161
3162             current = continuation;
3163             vars[((i >> 1) + 0) % numVars] = finalSum;
3164         }
3165     }
3166
3167     current->appendNew<ControlValue>(proc, Return, Origin(), vars[0]);
3168
3169     compile(proc);
3170
3171     double after = monotonicallyIncreasingTimeMS();
3172     dataLog(toCString("    That took ", after - before, " ms.\n"));
3173 }
3174
3175 void testSimplePatchpoint()
3176 {
3177     Procedure proc;
3178     BasicBlock* root = proc.addBlock();
3179     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3180     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3181     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
3182     patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
3183     patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
3184     patchpoint->setGenerator(
3185         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3186             AllowMacroScratchRegisterUsage allowScratch(jit);
3187             CHECK(params.reps.size() == 3);
3188             CHECK(params.reps[0].isGPR());
3189             CHECK(params.reps[1].isGPR());
3190             CHECK(params.reps[2].isGPR());
3191             jit.move(params.reps[1].gpr(), params.reps[0].gpr());
3192             jit.add32(params.reps[2].gpr(), params.reps[0].gpr());
3193         });
3194     root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
3195
3196     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
3197 }
3198
3199 void testSimplePatchpointWithoutOuputClobbersGPArgs()
3200 {
3201     Procedure proc;
3202     BasicBlock* root = proc.addBlock();
3203     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3204     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3205     Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
3206     Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
3207
3208     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
3209     patchpoint->clobber(RegisterSet(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1));
3210     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3211     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3212     patchpoint->setGenerator(
3213         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3214             AllowMacroScratchRegisterUsage allowScratch(jit);
3215             CHECK(params.reps.size() == 2);
3216             CHECK(params.reps[0].isGPR());
3217             CHECK(params.reps[1].isGPR());
3218             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params.reps[0].gpr());
3219             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params.reps[1].gpr());
3220             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR0);
3221             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR1);
3222         });
3223
3224     Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
3225     root->appendNew<ControlValue>(proc, Return, Origin(), result);
3226
3227     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
3228 }
3229
3230 void testSimplePatchpointWithOuputClobbersGPArgs()
3231 {
3232     // We can't predict where the output will be but we want to be sure it is not
3233     // one of the clobbered registers which is a bit hard to test.
3234     //
3235     // What we do is force the hand of our register allocator by clobbering absolutely
3236     // everything but 1. The only valid allocation is to give it to the result and
3237     // spill everything else.
3238
3239     Procedure proc;
3240     BasicBlock* root = proc.addBlock();
3241     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3242     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3243     Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
3244     Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
3245
3246     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin());
3247
3248     RegisterSet clobberAll = RegisterSet::allGPRs();
3249     clobberAll.exclude(RegisterSet::stackRegisters());
3250     clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
3251     clobberAll.clear(GPRInfo::argumentGPR2);
3252     patchpoint->clobber(clobberAll);
3253
3254     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3255     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3256
3257     patchpoint->setGenerator(
3258         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3259             AllowMacroScratchRegisterUsage allowScratch(jit);
3260             CHECK(params.reps.size() == 3);
3261             CHECK(params.reps[0].isGPR());
3262             CHECK(params.reps[1].isGPR());
3263             CHECK(params.reps[2].isGPR());
3264             jit.move(params.reps[1].gpr(), params.reps[0].gpr());
3265             jit.add64(params.reps[2].gpr(), params.reps[0].gpr());
3266
3267             clobberAll.forEach([&] (Reg reg) {
3268                 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), reg.gpr());
3269             });
3270         });
3271
3272     Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
3273         root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
3274     root->appendNew<ControlValue>(proc, Return, Origin(), result);
3275
3276     CHECK(compileAndRun<int>(proc, 1, 2) == 58);
3277 }
3278
3279 void testSimplePatchpointWithoutOuputClobbersFPArgs()
3280 {
3281     Procedure proc;
3282     BasicBlock* root = proc.addBlock();
3283     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3284     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
3285     Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
3286     Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
3287
3288     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
3289     patchpoint->clobber(RegisterSet(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1));
3290     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3291     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3292     patchpoint->setGenerator(
3293         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3294             AllowMacroScratchRegisterUsage allowScratch(jit);
3295             CHECK(params.reps.size() == 2);
3296             CHECK(params.reps[0].isFPR());
3297             CHECK(params.reps[1].isFPR());
3298             jit.moveZeroToDouble(params.reps[0].fpr());
3299             jit.moveZeroToDouble(params.reps[1].fpr());
3300             jit.moveZeroToDouble(FPRInfo::argumentFPR0);
3301             jit.moveZeroToDouble(FPRInfo::argumentFPR1);
3302         });
3303
3304     Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
3305     root->appendNew<ControlValue>(proc, Return, Origin(), result);
3306
3307     CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 4);
3308 }
3309
3310 void testSimplePatchpointWithOuputClobbersFPArgs()
3311 {
3312     Procedure proc;
3313     BasicBlock* root = proc.addBlock();
3314     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3315     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
3316     Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
3317     Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
3318
3319     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin());
3320
3321     RegisterSet clobberAll = RegisterSet::allFPRs();
3322     clobberAll.exclude(RegisterSet::stackRegisters());
3323     clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
3324     clobberAll.clear(FPRInfo::argumentFPR2);
3325     patchpoint->clobber(clobberAll);
3326
3327     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3328     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3329
3330     patchpoint->setGenerator(
3331         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3332             AllowMacroScratchRegisterUsage allowScratch(jit);
3333             CHECK(params.reps.size() == 3);
3334             CHECK(params.reps[0].isFPR());
3335             CHECK(params.reps[1].isFPR());
3336             CHECK(params.reps[2].isFPR());
3337             jit.addDouble(params.reps[1].fpr(), params.reps[2].fpr(), params.reps[0].fpr());
3338
3339             clobberAll.forEach([&] (Reg reg) {
3340                 jit.moveZeroToDouble(reg.fpr());
3341             });
3342         });
3343
3344     Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
3345         root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
3346     root->appendNew<ControlValue>(proc, Return, Origin(), result);
3347
3348     CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6);
3349 }
3350
3351 void testPatchpointCallArg()
3352 {
3353     Procedure proc;
3354     BasicBlock* root = proc.addBlock();
3355     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3356     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3357     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
3358     patchpoint->append(ConstrainedValue(arg1, ValueRep::stackArgument(0)));
3359     patchpoint->append(ConstrainedValue(arg2, ValueRep::stackArgument(8)));
3360     patchpoint->setGenerator(
3361         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3362             AllowMacroScratchRegisterUsage allowScratch(jit);
3363             CHECK(params.reps.size() == 3);
3364             CHECK(params.reps[0].isGPR());
3365             CHECK(params.reps[1].isStack());
3366             CHECK(params.reps[2].isStack());
3367             jit.load32(
3368                 CCallHelpers::Address(GPRInfo::callFrameRegister, params.reps[1].offsetFromFP()),
3369                 params.reps[0].gpr());
3370             jit.add32(
3371                 CCallHelpers::Address(GPRInfo::callFrameRegister, params.reps[2].offsetFromFP()),
3372                 params.reps[0].gpr());
3373         });
3374     root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
3375
3376     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
3377 }
3378
3379 void testPatchpointFixedRegister()
3380 {
3381     Procedure proc;
3382     BasicBlock* root = proc.addBlock();
3383     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3384     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3385     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
3386     patchpoint->append(ConstrainedValue(arg1, ValueRep(GPRInfo::regT0)));
3387     patchpoint->append(ConstrainedValue(arg2, ValueRep(GPRInfo::regT1)));
3388     patchpoint->setGenerator(
3389         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3390             AllowMacroScratchRegisterUsage allowScratch(jit);
3391             CHECK(params.reps.size() == 3);
3392             CHECK(params.reps[0].isGPR());
3393             CHECK(params.reps[1] == ValueRep(GPRInfo::regT0));
3394             CHECK(params.reps[2] == ValueRep(GPRInfo::regT1));
3395             GPRReg result = params.reps[0].gpr();
3396
3397             if (result == GPRInfo::regT1) {
3398                 jit.move(GPRInfo::regT1, result);
3399                 jit.add32(GPRInfo::regT0, result);
3400             } else {
3401                 jit.move(GPRInfo::regT0, result);
3402                 jit.add32(GPRInfo::regT1, result);
3403             }
3404         });
3405     root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
3406
3407     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
3408 }
3409
3410 void testPatchpointAny()
3411 {
3412     Procedure proc;
3413     BasicBlock* root = proc.addBlock();
3414     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3415     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3416     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
3417     patchpoint->append(ConstrainedValue(arg1, ValueRep::Any));
3418     patchpoint->append(ConstrainedValue(arg2, ValueRep::Any));
3419     patchpoint->setGenerator(
3420         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3421             AllowMacroScratchRegisterUsage allowScratch(jit);
3422             // We shouldn't have spilled the inputs, so we assert that they're in registers.
3423             CHECK(params.reps.size() == 3);
3424             CHECK(params.reps[0].isGPR());
3425             CHECK(params.reps[1].isGPR());
3426             CHECK(params.reps[2].isGPR());
3427             jit.move(params.reps[1].gpr(), params.reps[0].gpr());
3428             jit.add32(params.reps[2].gpr(), params.reps[0].gpr());
3429         });
3430     root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
3431
3432     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
3433 }
3434
3435 void testPatchpointAnyImm()
3436 {
3437     Procedure proc;
3438     BasicBlock* root = proc.addBlock();
3439     Value* arg1 = root->appendNew<Value>(
3440         proc, Trunc, Origin(),
3441         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3442     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
3443     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
3444     patchpoint->append(ConstrainedValue(arg1, ValueRep::Any));
3445     patchpoint->append(ConstrainedValue(arg2, ValueRep::Any));
3446     patchpoint->setGenerator(
3447         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3448             AllowMacroScratchRegisterUsage allowScratch(jit);
3449             CHECK(params.reps.size() == 3);
3450             CHECK(params.reps[0].isGPR());
3451             CHECK(params.reps[1].isGPR());
3452             CHECK(params.reps[2].isConstant());
3453             CHECK(params.reps[2].value() == 42);
3454             jit.add32(
3455                 CCallHelpers::TrustedImm32(static_cast<int32_t>(params.reps[2].value())),
3456                 params.reps[1].gpr(), params.reps[0].gpr());
3457         });
3458     root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
3459
3460     CHECK(compileAndRun<int>(proc, 1) == 43);
3461 }
3462
3463 void testPatchpointManyImms()
3464 {
3465     Procedure proc;
3466     BasicBlock* root = proc.addBlock();
3467     Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), 42);
3468     Value* arg2 = root->appendNew<Const64Value>(proc, Origin(), 43);
3469     Value* arg3 = root->appendNew<Const64Value>(proc, Origin(), 43000000000000ll);
3470     Value* arg4 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
3471     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
3472     patchpoint->append(ConstrainedValue(arg1, ValueRep::Any));
3473     patchpoint->append(ConstrainedValue(arg2, ValueRep::Any));
3474     patchpoint->append(ConstrainedValue(arg3, ValueRep::Any));
3475     patchpoint->append(ConstrainedValue(arg4, ValueRep::Any));
3476     patchpoint->setGenerator(
3477         [&] (CCallHelpers&, const StackmapGenerationParams& params) {
3478             CHECK(params.reps.size() == 4);
3479             CHECK(params.reps[0] == ValueRep::constant(42));
3480             CHECK(params.reps[1] == ValueRep::constant(43));
3481             CHECK(params.reps[2] == ValueRep::constant(43000000000000ll));
3482             CHECK(params.reps[3] == ValueRep::constant(bitwise_cast<int64_t>(42.5)));
3483         });
3484     root->appendNew<ControlValue>(
3485         proc, Return, Origin(),
3486         root->appendNew<Const32Value>(proc, Origin(), 0));
3487
3488     CHECK(!compileAndRun<int>(proc));
3489 }
3490
3491 void testSimpleCheck()
3492 {
3493     Procedure proc;
3494     BasicBlock* root = proc.addBlock();
3495     Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3496     CheckValue* check = root->appendNew<CheckValue>(proc, Check, Origin(), arg);
3497     check->setGenerator(
3498         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3499             AllowMacroScratchRegisterUsage allowScratch(jit);
3500             CHECK(params.reps.size() == 1);
3501
3502             // This should always work because a function this simple should never have callee
3503             // saves.
3504             jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
3505             jit.emitFunctionEpilogue();
3506             jit.ret();
3507         });
3508     root->appendNew<ControlValue>(
3509         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3510
3511     auto code = compile(proc);
3512     
3513     CHECK(invoke<int>(*code, 0) == 0);
3514     CHECK(invoke<int>(*code, 1) == 42);
3515 }
3516
3517 void testCheckLessThan()
3518 {
3519     Procedure proc;
3520     BasicBlock* root = proc.addBlock();
3521     Value* arg = root->appendNew<Value>(
3522         proc, Trunc, Origin(),
3523         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3524     CheckValue* check = root->appendNew<CheckValue>(
3525         proc, Check, Origin(),
3526         root->appendNew<Value>(
3527             proc, LessThan, Origin(), arg,
3528             root->appendNew<Const32Value>(proc, Origin(), 42)));
3529     check->setGenerator(
3530         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3531             AllowMacroScratchRegisterUsage allowScratch(jit);
3532             CHECK(params.reps.size() == 1);
3533
3534             // This should always work because a function this simple should never have callee
3535             // saves.
3536             jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
3537             jit.emitFunctionEpilogue();
3538             jit.ret();
3539         });
3540     root->appendNew<ControlValue>(
3541         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3542
3543     auto code = compile(proc);
3544     
3545     CHECK(invoke<int>(*code, 42) == 0);
3546     CHECK(invoke<int>(*code, 1000) == 0);
3547     CHECK(invoke<int>(*code, 41) == 42);
3548     CHECK(invoke<int>(*code, 0) == 42);
3549     CHECK(invoke<int>(*code, -1) == 42);
3550 }
3551
3552 void testCheckMegaCombo()
3553 {
3554     Procedure proc;
3555     BasicBlock* root = proc.addBlock();
3556     Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3557     Value* index = root->appendNew<Value>(
3558         proc, ZExt32, Origin(),
3559         root->appendNew<Value>(
3560             proc, Trunc, Origin(),
3561             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3562
3563     Value* ptr = root->appendNew<Value>(
3564         proc, Add, Origin(), base,
3565         root->appendNew<Value>(
3566             proc, Shl, Origin(), index,
3567             root->appendNew<Const32Value>(proc, Origin(), 1)));
3568     
3569     CheckValue* check = root->appendNew<CheckValue>(
3570         proc, Check, Origin(),
3571         root->appendNew<Value>(
3572             proc, LessThan, Origin(),
3573             root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr),
3574             root->appendNew<Const32Value>(proc, Origin(), 42)));
3575     check->setGenerator(
3576         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3577             AllowMacroScratchRegisterUsage allowScratch(jit);
3578             CHECK(params.reps.size() == 1);
3579
3580             // This should always work because a function this simple should never have callee
3581             // saves.
3582             jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
3583             jit.emitFunctionEpilogue();
3584             jit.ret();
3585         });
3586     root->appendNew<ControlValue>(
3587         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3588
3589     auto code = compile(proc);
3590
3591     int8_t value;
3592     value = 42;
3593     CHECK(invoke<int>(*code, &value - 2, 1) == 0);
3594     value = 127;
3595     CHECK(invoke<int>(*code, &value - 2, 1) == 0);
3596     value = 41;
3597     CHECK(invoke<int>(*code, &value - 2, 1) == 42);
3598     value = 0;
3599     CHECK(invoke<int>(*code, &value - 2, 1) == 42);
3600     value = -1;
3601     CHECK(invoke<int>(*code, &value - 2, 1) == 42);
3602 }
3603
3604 void testCheckAddImm()
3605 {
3606     Procedure proc;
3607     BasicBlock* root = proc.addBlock();
3608     Value* arg1 = root->appendNew<Value>(
3609         proc, Trunc, Origin(),
3610         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3611     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
3612     CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
3613     checkAdd->append(arg1);
3614     checkAdd->append(arg2);
3615     checkAdd->setGenerator(
3616         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3617             AllowMacroScratchRegisterUsage allowScratch(jit);
3618             CHECK(params.reps.size() == 4);
3619             CHECK(params.reps[2].isGPR());
3620             CHECK(params.reps[3].isConstant());
3621             CHECK(params.reps[3].value() == 42);
3622             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3623             jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1);
3624             jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3625             jit.emitFunctionEpilogue();
3626             jit.ret();
3627         });
3628     root->appendNew<ControlValue>(
3629         proc, Return, Origin(),
3630         root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
3631
3632     auto code = compile(proc);
3633
3634     CHECK(invoke<double>(*code, 0) == 42.0);
3635     CHECK(invoke<double>(*code, 1) == 43.0);
3636     CHECK(invoke<double>(*code, 42) == 84.0);
3637     CHECK(invoke<double>(*code, 2147483647) == 2147483689.0);
3638 }
3639
3640 void testCheckAddImmCommute()
3641 {
3642     Procedure proc;
3643     BasicBlock* root = proc.addBlock();
3644     Value* arg1 = root->appendNew<Value>(
3645         proc, Trunc, Origin(),
3646         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3647     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
3648     CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg2, arg1);
3649     checkAdd->append(arg1);
3650     checkAdd->append(arg2);
3651     checkAdd->setGenerator(
3652         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3653             AllowMacroScratchRegisterUsage allowScratch(jit);
3654             CHECK(params.reps.size() == 4);
3655             CHECK(params.reps[2].isGPR());
3656             CHECK(params.reps[3].isConstant());
3657             CHECK(params.reps[3].value() == 42);
3658             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3659             jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1);
3660             jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3661             jit.emitFunctionEpilogue();
3662             jit.ret();
3663         });
3664     root->appendNew<ControlValue>(
3665         proc, Return, Origin(),
3666         root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
3667
3668     auto code = compile(proc);
3669
3670     CHECK(invoke<double>(*code, 0) == 42.0);
3671     CHECK(invoke<double>(*code, 1) == 43.0);
3672     CHECK(invoke<double>(*code, 42) == 84.0);
3673     CHECK(invoke<double>(*code, 2147483647) == 2147483689.0);
3674 }
3675
3676 void testCheckAddImmSomeRegister()
3677 {
3678     Procedure proc;
3679     BasicBlock* root = proc.addBlock();
3680     Value* arg1 = root->appendNew<Value>(
3681         proc, Trunc, Origin(),
3682         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3683     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
3684     CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
3685     checkAdd->appendSomeRegister(arg1);
3686     checkAdd->appendSomeRegister(arg2);
3687     checkAdd->setGenerator(
3688         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3689             AllowMacroScratchRegisterUsage allowScratch(jit);
3690             CHECK(params.reps.size() == 4);
3691             CHECK(params.reps[2].isGPR());
3692             CHECK(params.reps[3].isGPR());
3693             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3694             jit.convertInt32ToDouble(params.reps[3].gpr(), FPRInfo::fpRegT1);
3695             jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3696             jit.emitFunctionEpilogue();
3697             jit.ret();
3698         });
3699     root->appendNew<ControlValue>(
3700         proc, Return, Origin(),
3701         root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
3702
3703     auto code = compile(proc);
3704
3705     CHECK(invoke<double>(*code, 0) == 42.0);
3706     CHECK(invoke<double>(*code, 1) == 43.0);
3707     CHECK(invoke<double>(*code, 42) == 84.0);
3708     CHECK(invoke<double>(*code, 2147483647) == 2147483689.0);
3709 }
3710
3711 void testCheckAdd()
3712 {
3713     Procedure proc;
3714     BasicBlock* root = proc.addBlock();
3715     Value* arg1 = root->appendNew<Value>(
3716         proc, Trunc, Origin(),
3717         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3718     Value* arg2 = root->appendNew<Value>(
3719         proc, Trunc, Origin(),
3720         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3721     CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
3722     checkAdd->appendSomeRegister(arg1);
3723     checkAdd->appendSomeRegister(arg2);
3724     checkAdd->setGenerator(
3725         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3726             AllowMacroScratchRegisterUsage allowScratch(jit);
3727             CHECK(params.reps.size() == 4);
3728             CHECK(params.reps[2].isGPR());
3729             CHECK(params.reps[3].isGPR());
3730             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3731             jit.convertInt32ToDouble(params.reps[3].gpr(), FPRInfo::fpRegT1);
3732             jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3733             jit.emitFunctionEpilogue();
3734             jit.ret();
3735         });
3736     root->appendNew<ControlValue>(
3737         proc, Return, Origin(),
3738         root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
3739
3740     auto code = compile(proc);
3741
3742     CHECK(invoke<double>(*code, 0, 42) == 42.0);
3743     CHECK(invoke<double>(*code, 1, 42) == 43.0);
3744     CHECK(invoke<double>(*code, 42, 42) == 84.0);
3745     CHECK(invoke<double>(*code, 2147483647, 42) == 2147483689.0);
3746 }
3747
3748 void testCheckAdd64()
3749 {
3750     Procedure proc;
3751     BasicBlock* root = proc.addBlock();
3752     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3753     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3754     CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
3755     checkAdd->appendSomeRegister(arg1);
3756     checkAdd->appendSomeRegister(arg2);
3757     checkAdd->setGenerator(
3758         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3759             AllowMacroScratchRegisterUsage allowScratch(jit);
3760             CHECK(params.reps.size() == 4);
3761             CHECK(params.reps[2].isGPR());
3762             CHECK(params.reps[3].isGPR());
3763             jit.convertInt64ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3764             jit.convertInt64ToDouble(params.reps[3].gpr(), FPRInfo::fpRegT1);
3765             jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3766             jit.emitFunctionEpilogue();
3767             jit.ret();
3768         });
3769     root->appendNew<ControlValue>(
3770         proc, Return, Origin(),
3771         root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
3772
3773     auto code = compile(proc);
3774
3775     CHECK(invoke<double>(*code, 0ll, 42ll) == 42.0);
3776     CHECK(invoke<double>(*code, 1ll, 42ll) == 43.0);
3777     CHECK(invoke<double>(*code, 42ll, 42ll) == 84.0);
3778     CHECK(invoke<double>(*code, 9223372036854775807ll, 42ll) == static_cast<double>(9223372036854775807ll) + 42.0);
3779 }
3780
3781 void testCheckAddFold(int a, int b)
3782 {
3783     Procedure proc;
3784     BasicBlock* root = proc.addBlock();
3785     Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
3786     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
3787     CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
3788     checkAdd->setGenerator(
3789         [&] (CCallHelpers&, const StackmapGenerationParams&) {
3790             CHECK(!"Should have been folded");
3791         });
3792     root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd);
3793
3794     auto code = compile(proc);
3795
3796     CHECK(invoke<int>(*code) == a + b);
3797 }
3798
3799 void testCheckAddFoldFail(int a, int b)
3800 {
3801     Procedure proc;
3802     BasicBlock* root = proc.addBlock();
3803     Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
3804     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
3805     CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
3806     checkAdd->setGenerator(
3807         [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
3808             AllowMacroScratchRegisterUsage allowScratch(jit);
3809             jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
3810             jit.emitFunctionEpilogue();
3811             jit.ret();
3812         });
3813     root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd);
3814
3815     auto code = compile(proc);
3816
3817     CHECK(invoke<int>(*code) == 42);
3818 }
3819
3820 void testCheckSubImm()
3821 {
3822     Procedure proc;
3823     BasicBlock* root = proc.addBlock();
3824     Value* arg1 = root->appendNew<Value>(
3825         proc, Trunc, Origin(),
3826         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3827     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
3828     CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
3829     checkSub->append(arg1);
3830     checkSub->append(arg2);
3831     checkSub->setGenerator(
3832         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3833             AllowMacroScratchRegisterUsage allowScratch(jit);
3834             CHECK(params.reps.size() == 4);
3835             CHECK(params.reps[2].isGPR());
3836             CHECK(params.reps[3].isConstant());
3837             CHECK(params.reps[3].value() == 42);
3838             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3839             jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1);
3840             jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3841             jit.emitFunctionEpilogue();
3842             jit.ret();
3843         });
3844     root->appendNew<ControlValue>(
3845         proc, Return, Origin(),
3846         root->appendNew<Value>(proc, IToD, Origin(), checkSub));
3847
3848     auto code = compile(proc);
3849
3850     CHECK(invoke<double>(*code, 0) == -42.0);
3851     CHECK(invoke<double>(*code, 1) == -41.0);
3852     CHECK(invoke<double>(*code, 42) == 0.0);
3853     CHECK(invoke<double>(*code, -2147483647) == -2147483689.0);
3854 }
3855
3856 void testCheckSubBadImm()
3857 {
3858     Procedure proc;
3859     BasicBlock* root = proc.addBlock();
3860     Value* arg1 = root->appendNew<Value>(
3861         proc, Trunc, Origin(),
3862         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3863     int32_t badImm = std::numeric_limits<int>::min();
3864     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), badImm);
3865     CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
3866     checkSub->append(arg1);
3867     checkSub->append(arg2);
3868     checkSub->setGenerator(
3869         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3870             AllowMacroScratchRegisterUsage allowScratch(jit);
3871             CHECK(params.reps.size() == 4);
3872             CHECK(params.reps[2].isGPR());
3873             CHECK(params.reps[3].isConstant());
3874             CHECK(params.reps[3].value() == badImm);
3875             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3876             jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(badImm), FPRInfo::fpRegT1);
3877             jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3878             jit.emitFunctionEpilogue();
3879             jit.ret();
3880         });
3881     root->appendNew<ControlValue>(
3882         proc, Return, Origin(),
3883         root->appendNew<Value>(proc, IToD, Origin(), checkSub));
3884
3885     auto code = compile(proc);
3886
3887     CHECK(invoke<double>(*code, 0) == -static_cast<double>(badImm));
3888     CHECK(invoke<double>(*code, -1) == -static_cast<double>(badImm) - 1);
3889     CHECK(invoke<double>(*code, 1) == -static_cast<double>(badImm) + 1);
3890     CHECK(invoke<double>(*code, 42) == -static_cast<double>(badImm) + 42);
3891 }
3892
3893 void testCheckSub()
3894 {
3895     Procedure proc;
3896     BasicBlock* root = proc.addBlock();
3897     Value* arg1 = root->appendNew<Value>(
3898         proc, Trunc, Origin(),
3899         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3900     Value* arg2 = root->appendNew<Value>(
3901         proc, Trunc, Origin(),
3902         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3903     CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
3904     checkSub->append(arg1);
3905     checkSub->append(arg2);
3906     checkSub->setGenerator(
3907         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3908             AllowMacroScratchRegisterUsage allowScratch(jit);
3909             CHECK(params.reps.size() == 4);
3910             CHECK(params.reps[2].isGPR());
3911             CHECK(params.reps[3].isGPR());
3912             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3913             jit.convertInt32ToDouble(params.reps[3].gpr(), FPRInfo::fpRegT1);
3914             jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3915             jit.emitFunctionEpilogue();
3916             jit.ret();
3917         });
3918     root->appendNew<ControlValue>(
3919         proc, Return, Origin(),
3920         root->appendNew<Value>(proc, IToD, Origin(), checkSub));
3921
3922     auto code = compile(proc);
3923
3924     CHECK(invoke<double>(*code, 0, 42) == -42.0);
3925     CHECK(invoke<double>(*code, 1, 42) == -41.0);
3926     CHECK(invoke<double>(*code, 42, 42) == 0.0);
3927     CHECK(invoke<double>(*code, -2147483647, 42) == -2147483689.0);
3928 }
3929
3930 NEVER_INLINE double doubleSub(double a, double b)
3931 {
3932     return a - b;
3933 }
3934
3935 void testCheckSub64()
3936 {
3937     Procedure proc;
3938     BasicBlock* root = proc.addBlock();
3939     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3940     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3941     CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
3942     checkSub->append(arg1);
3943     checkSub->append(arg2);
3944     checkSub->setGenerator(
3945         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3946             AllowMacroScratchRegisterUsage allowScratch(jit);
3947             CHECK(params.reps.size() == 4);
3948             CHECK(params.reps[2].isGPR());
3949             CHECK(params.reps[3].isGPR());
3950             jit.convertInt64ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT0);
3951             jit.convertInt64ToDouble(params.reps[3].gpr(), FPRInfo::fpRegT1);
3952             jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
3953             jit.emitFunctionEpilogue();
3954             jit.ret();
3955         });
3956     root->appendNew<ControlValue>(
3957         proc, Return, Origin(),
3958         root->appendNew<Value>(proc, IToD, Origin(), checkSub));
3959
3960     auto code = compile(proc);
3961
3962     CHECK(invoke<double>(*code, 0ll, 42ll) == -42.0);
3963     CHECK(invoke<double>(*code, 1ll, 42ll) == -41.0);
3964     CHECK(invoke<double>(*code, 42ll, 42ll) == 0.0);
3965     CHECK(invoke<double>(*code, -9223372036854775807ll, 42ll) == doubleSub(static_cast<double>(-9223372036854775807ll), 42.0));
3966 }
3967
3968 void testCheckSubFold(int a, int b)
3969 {
3970     Procedure proc;
3971     BasicBlock* root = proc.addBlock();
3972     Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
3973     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
3974     CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
3975     checkSub->setGenerator(
3976         [&] (CCallHelpers&, const StackmapGenerationParams&) {
3977             CHECK(!"Should have been folded");
3978         });
3979     root->appendNew<ControlValue>(proc, Return, Origin(), checkSub);
3980
3981     auto code = compile(proc);
3982
3983     CHECK(invoke<int>(*code) == a - b);
3984 }
3985
3986 void testCheckSubFoldFail(int a, int b)
3987 {
3988     Procedure proc;
3989     BasicBlock* root = proc.addBlock();
3990     Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
3991     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
3992     CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
3993     checkSub->setGenerator(
3994         [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
3995             AllowMacroScratchRegisterUsage allowScratch(jit);
3996             jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
3997             jit.emitFunctionEpilogue();
3998             jit.ret();
3999         });
4000     root->appendNew<ControlValue>(proc, Return, Origin(), checkSub);
4001
4002     auto code = compile(proc);
4003
4004     CHECK(invoke<int>(*code) == 42);
4005 }
4006
4007 void testCheckNeg()
4008 {
4009     Procedure proc;
4010     BasicBlock* root = proc.addBlock();
4011     Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), 0);
4012     Value* arg2 = root->appendNew<Value>(
4013         proc, Trunc, Origin(),
4014         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4015     CheckValue* checkNeg = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
4016     checkNeg->append(arg2);
4017     checkNeg->setGenerator(
4018         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
4019             AllowMacroScratchRegisterUsage allowScratch(jit);
4020             CHECK(params.reps.size() == 3);
4021             CHECK(params.reps[2].isGPR());
4022             jit.convertInt32ToDouble(params.reps[2].gpr(), FPRInfo::fpRegT1);
4023             jit.negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
4024             jit.emitFunctionEpilogue();
4025             jit.ret();
4026         });
4027     root->appendNew<ControlValue>(
4028         proc, Return, Origin(),
4029         root->appendNew<Value>(proc, IToD, Origin(), checkNeg));
4030
4031     auto code = compile(proc);
4032
4033     CHECK(invoke<double>(*code, 0) == 0.0);
4034     CHECK(invoke<double>(*code, 1) == -1.0);
4035     CHECK(invoke<double>(*code, 42) == -42.0);
4036     CHECK(invoke<double>(*code, -2147483647 - 1) == 2147483648.0);
4037 }
4038
4039 void testCheckNeg64()
4040 {
4041     Procedure proc;
4042     BasicBlock* root = proc.addBlock();
4043     Value* arg1 = root->appendNew<Const64Value>(proc, Origin(), 0);
4044     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4045     CheckValue* checkNeg = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
4046     checkNeg->append(arg2);
4047     checkNeg->setGenerator(