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