[B3] Add a test for CCall with double arguments and results
[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 "B3UpsilonValue.h"
39 #include "B3ValueInlines.h"
40 #include "CCallHelpers.h"
41 #include "InitializeThreading.h"
42 #include "JSCInlines.h"
43 #include "LinkBuffer.h"
44 #include "VM.h"
45 #include <wtf/Lock.h>
46 #include <wtf/NumberOfCores.h>
47 #include <wtf/Threading.h>
48
49 // We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous.
50 static bool hiddenTruthBecauseNoReturnIsStupid() { return true; }
51
52 static void usage()
53 {
54     dataLog("Usage: testb3 [<filter>]\n");
55     if (hiddenTruthBecauseNoReturnIsStupid())
56         exit(1);
57 }
58
59 #if ENABLE(B3_JIT)
60
61 using namespace JSC;
62 using namespace JSC::B3;
63
64 namespace {
65
66 // Nothing fancy for now; we just use the existing WTF assertion machinery.
67 #define CHECK(x) RELEASE_ASSERT(x)
68
69 VM* vm;
70
71 std::unique_ptr<Compilation> compile(Procedure& procedure)
72 {
73     return std::make_unique<Compilation>(*vm, procedure);
74 }
75
76 template<typename T, typename... Arguments>
77 T invoke(const Compilation& code, Arguments... arguments)
78 {
79     T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(code.code().executableAddress());
80     return function(arguments...);
81 }
82
83 template<typename T, typename... Arguments>
84 T compileAndRun(Procedure& procedure, Arguments... arguments)
85 {
86     return invoke<T>(*compile(procedure), arguments...);
87 }
88
89 void test42()
90 {
91     Procedure proc;
92     BasicBlock* root = proc.addBlock();
93     Value* const42 = root->appendNew<Const32Value>(proc, Origin(), 42);
94     root->appendNew<ControlValue>(proc, Return, Origin(), const42);
95
96     CHECK(compileAndRun<int>(proc) == 42);
97 }
98
99 void testLoad42()
100 {
101     Procedure proc;
102     BasicBlock* root = proc.addBlock();
103     int x = 42;
104     root->appendNew<ControlValue>(
105         proc, Return, Origin(),
106         root->appendNew<MemoryValue>(
107             proc, Load, Int32, Origin(),
108             root->appendNew<ConstPtrValue>(proc, Origin(), &x)));
109
110     CHECK(compileAndRun<int>(proc) == 42);
111 }
112
113 void testArg(int argument)
114 {
115     Procedure proc;
116     BasicBlock* root = proc.addBlock();
117     root->appendNew<ControlValue>(
118         proc, Return, Origin(),
119         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
120
121     CHECK(compileAndRun<int>(proc, argument) == argument);
122 }
123
124 void testReturnConst64(int64_t value)
125 {
126     Procedure proc;
127     BasicBlock* root = proc.addBlock();
128     root->appendNew<ControlValue>(
129         proc, Return, Origin(),
130         root->appendNew<Const64Value>(proc, Origin(), value));
131
132     CHECK(compileAndRun<int64_t>(proc) == value);
133 }
134
135 void testAddArgs(int a, int b)
136 {
137     Procedure proc;
138     BasicBlock* root = proc.addBlock();
139     root->appendNew<ControlValue>(
140         proc, Return, Origin(),
141         root->appendNew<Value>(
142             proc, Add, Origin(),
143             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
144             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
145
146     CHECK(compileAndRun<int>(proc, a, b) == a + b);
147 }
148
149 void testAddArgImm(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<Const64Value>(proc, Origin(), b)));
159
160     CHECK(compileAndRun<int>(proc, a) == a + b);
161 }
162
163 void testAddImmArg(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<Const64Value>(proc, Origin(), a),
172             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
173
174     CHECK(compileAndRun<int>(proc, b) == a + b);
175 }
176
177 void testAddArgs32(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<Value>(
186                 proc, Trunc, Origin(),
187                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
188             root->appendNew<Value>(
189                 proc, Trunc, Origin(),
190                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
191
192     CHECK(compileAndRun<int>(proc, a, b) == a + b);
193 }
194
195 void testSubArgs(int a, int b)
196 {
197     Procedure proc;
198     BasicBlock* root = proc.addBlock();
199     root->appendNew<ControlValue>(
200         proc, Return, Origin(),
201         root->appendNew<Value>(
202             proc, Sub, Origin(),
203             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
204             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
205
206     CHECK(compileAndRun<int>(proc, a, b) == a - b);
207 }
208
209 void testSubArgImm(int64_t a, int64_t b)
210 {
211     Procedure proc;
212     BasicBlock* root = proc.addBlock();
213     root->appendNew<ControlValue>(
214         proc, Return, Origin(),
215         root->appendNew<Value>(
216             proc, Sub, Origin(),
217             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
218             root->appendNew<Const64Value>(proc, Origin(), b)));
219
220     CHECK(compileAndRun<int64_t>(proc, a) == a - b);
221 }
222
223 void testSubImmArg(int a, int b)
224 {
225     Procedure proc;
226     BasicBlock* root = proc.addBlock();
227     root->appendNew<ControlValue>(
228         proc, Return, Origin(),
229         root->appendNew<Value>(
230             proc, Sub, Origin(),
231             root->appendNew<Const64Value>(proc, Origin(), a),
232             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
233
234     CHECK(compileAndRun<int>(proc, b) == a - b);
235 }
236
237 void testSubArgs32(int a, int b)
238 {
239     Procedure proc;
240     BasicBlock* root = proc.addBlock();
241     root->appendNew<ControlValue>(
242         proc, Return, Origin(),
243         root->appendNew<Value>(
244             proc, Sub, Origin(),
245             root->appendNew<Value>(
246                 proc, Trunc, Origin(),
247                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
248             root->appendNew<Value>(
249                 proc, Trunc, Origin(),
250                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
251
252     CHECK(compileAndRun<int>(proc, a, b) == a - b);
253 }
254
255 void testSubArgImm32(int a, int b)
256 {
257     Procedure proc;
258     BasicBlock* root = proc.addBlock();
259     root->appendNew<ControlValue>(
260         proc, Return, Origin(),
261         root->appendNew<Value>(
262             proc, Sub, Origin(),
263             root->appendNew<Value>(
264                 proc, Trunc, Origin(),
265                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
266             root->appendNew<Const32Value>(proc, Origin(), b)));
267
268     CHECK(compileAndRun<int>(proc, a) == a - b);
269 }
270
271 void testSubImmArg32(int a, int b)
272 {
273     Procedure proc;
274     BasicBlock* root = proc.addBlock();
275     root->appendNew<ControlValue>(
276         proc, Return, Origin(),
277         root->appendNew<Value>(
278             proc, Sub, Origin(),
279             root->appendNew<Const32Value>(proc, Origin(), a),
280             root->appendNew<Value>(
281                 proc, Trunc, Origin(),
282                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
283
284     CHECK(compileAndRun<int>(proc, b) == a - b);
285 }
286
287 void testBitAndArgs(int64_t a, int64_t b)
288 {
289     Procedure proc;
290     BasicBlock* root = proc.addBlock();
291     root->appendNew<ControlValue>(
292         proc, Return, Origin(),
293         root->appendNew<Value>(
294             proc, BitAnd, Origin(),
295             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
296             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
297
298     CHECK(compileAndRun<int64_t>(proc, a, b) == (a & b));
299 }
300
301 void testBitAndSameArg(int64_t a)
302 {
303     Procedure proc;
304     BasicBlock* root = proc.addBlock();
305     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
306     root->appendNew<ControlValue>(
307         proc, Return, Origin(),
308         root->appendNew<Value>(
309             proc, BitAnd, Origin(),
310             argument,
311             argument));
312
313     CHECK(compileAndRun<int64_t>(proc, a) == a);
314 }
315
316 void testBitAndImms(int64_t a, int64_t b)
317 {
318     Procedure proc;
319     BasicBlock* root = proc.addBlock();
320     root->appendNew<ControlValue>(
321         proc, Return, Origin(),
322         root->appendNew<Value>(
323             proc, BitAnd, Origin(),
324             root->appendNew<Const64Value>(proc, Origin(), a),
325             root->appendNew<Const64Value>(proc, Origin(), b)));
326
327     CHECK(compileAndRun<int64_t>(proc) == (a & b));
328 }
329
330 void testBitAndArgImm(int64_t a, int64_t b)
331 {
332     Procedure proc;
333     BasicBlock* root = proc.addBlock();
334     root->appendNew<ControlValue>(
335         proc, Return, Origin(),
336         root->appendNew<Value>(
337             proc, BitAnd, Origin(),
338             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
339             root->appendNew<Const64Value>(proc, Origin(), b)));
340
341     CHECK(compileAndRun<int64_t>(proc, a) == (a & b));
342 }
343
344 void testBitAndImmArg(int64_t a, int64_t b)
345 {
346     Procedure proc;
347     BasicBlock* root = proc.addBlock();
348     root->appendNew<ControlValue>(
349         proc, Return, Origin(),
350         root->appendNew<Value>(
351             proc, BitAnd, Origin(),
352             root->appendNew<Const64Value>(proc, Origin(), a),
353             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
354
355     CHECK(compileAndRun<int64_t>(proc, b) == (a & b));
356 }
357
358 void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c)
359 {
360     Procedure proc;
361     BasicBlock* root = proc.addBlock();
362     Value* innerBitAnd = root->appendNew<Value>(
363         proc, BitAnd, Origin(),
364         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
365         root->appendNew<Const64Value>(proc, Origin(), b));
366     root->appendNew<ControlValue>(
367         proc, Return, Origin(),
368         root->appendNew<Value>(
369             proc, BitAnd, Origin(),
370             innerBitAnd,
371             root->appendNew<Const64Value>(proc, Origin(), c)));
372
373     CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c));
374 }
375
376 void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c)
377 {
378     Procedure proc;
379     BasicBlock* root = proc.addBlock();
380     Value* innerBitAnd = root->appendNew<Value>(
381         proc, BitAnd, Origin(),
382         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
383         root->appendNew<Const64Value>(proc, Origin(), c));
384     root->appendNew<ControlValue>(
385         proc, Return, Origin(),
386         root->appendNew<Value>(
387             proc, BitAnd, Origin(),
388             root->appendNew<Const64Value>(proc, Origin(), a),
389             innerBitAnd));
390
391     CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c)));
392 }
393
394 void testBitAndArgs32(int a, int b)
395 {
396     Procedure proc;
397     BasicBlock* root = proc.addBlock();
398     root->appendNew<ControlValue>(
399         proc, Return, Origin(),
400         root->appendNew<Value>(
401             proc, BitAnd, Origin(),
402             root->appendNew<Value>(
403                 proc, Trunc, Origin(),
404                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
405             root->appendNew<Value>(
406                 proc, Trunc, Origin(),
407                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
408
409     CHECK(compileAndRun<int>(proc, a, b) == (a & b));
410 }
411
412 void testBitAndSameArg32(int a)
413 {
414     Procedure proc;
415     BasicBlock* root = proc.addBlock();
416     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
417         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
418     root->appendNew<ControlValue>(
419         proc, Return, Origin(),
420         root->appendNew<Value>(
421             proc, BitAnd, Origin(),
422             argument,
423             argument));
424
425     CHECK(compileAndRun<int>(proc, a) == a);
426 }
427
428 void testBitAndImms32(int a, int b)
429 {
430     Procedure proc;
431     BasicBlock* root = proc.addBlock();
432     root->appendNew<ControlValue>(
433         proc, Return, Origin(),
434         root->appendNew<Value>(
435             proc, BitAnd, Origin(),
436             root->appendNew<Const32Value>(proc, Origin(), a),
437             root->appendNew<Const32Value>(proc, Origin(), b)));
438
439     CHECK(compileAndRun<int>(proc) == (a & b));
440 }
441
442 void testBitAndArgImm32(int a, int b)
443 {
444     Procedure proc;
445     BasicBlock* root = proc.addBlock();
446     root->appendNew<ControlValue>(
447         proc, Return, Origin(),
448         root->appendNew<Value>(
449             proc, BitAnd, Origin(),
450             root->appendNew<Value>(
451                 proc, Trunc, Origin(),
452                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
453             root->appendNew<Const32Value>(proc, Origin(), b)));
454
455     CHECK(compileAndRun<int>(proc, a) == (a & b));
456 }
457
458 void testBitAndImmArg32(int a, int b)
459 {
460     Procedure proc;
461     BasicBlock* root = proc.addBlock();
462     root->appendNew<ControlValue>(
463         proc, Return, Origin(),
464         root->appendNew<Value>(
465             proc, BitAnd, Origin(),
466             root->appendNew<Const32Value>(proc, Origin(), a),
467             root->appendNew<Value>(
468                 proc, Trunc, Origin(),
469                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
470
471     CHECK(compileAndRun<int>(proc, b) == (a & b));
472 }
473
474 void testBitAndBitAndArgImmImm32(int a, int b, int c)
475 {
476     Procedure proc;
477     BasicBlock* root = proc.addBlock();
478     Value* innerBitAnd = root->appendNew<Value>(
479         proc, BitAnd, Origin(),
480         root->appendNew<Value>(
481             proc, Trunc, Origin(),
482             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
483         root->appendNew<Const32Value>(proc, Origin(), b));
484     root->appendNew<ControlValue>(
485         proc, Return, Origin(),
486         root->appendNew<Value>(
487             proc, BitAnd, Origin(),
488             innerBitAnd,
489             root->appendNew<Const32Value>(proc, Origin(), c)));
490
491     CHECK(compileAndRun<int>(proc, a) == ((a & b) & c));
492 }
493
494 void testBitAndImmBitAndArgImm32(int a, int b, int c)
495 {
496     Procedure proc;
497     BasicBlock* root = proc.addBlock();
498     Value* innerBitAnd = root->appendNew<Value>(
499         proc, BitAnd, Origin(),
500         root->appendNew<Value>(
501             proc, Trunc, Origin(),
502             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
503         root->appendNew<Const32Value>(proc, Origin(), c));
504     root->appendNew<ControlValue>(
505         proc, Return, Origin(),
506         root->appendNew<Value>(
507             proc, BitAnd, Origin(),
508             root->appendNew<Const32Value>(proc, Origin(), a),
509             innerBitAnd));
510
511     CHECK(compileAndRun<int>(proc, b) == (a & (b & c)));
512 }
513
514 void testBitOrArgs(int64_t a, int64_t b)
515 {
516     Procedure proc;
517     BasicBlock* root = proc.addBlock();
518     root->appendNew<ControlValue>(
519         proc, Return, Origin(),
520         root->appendNew<Value>(
521             proc, BitOr, Origin(),
522             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
523             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
524
525     CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b));
526 }
527
528 void testBitOrSameArg(int64_t a)
529 {
530     Procedure proc;
531     BasicBlock* root = proc.addBlock();
532     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
533     root->appendNew<ControlValue>(
534         proc, Return, Origin(),
535         root->appendNew<Value>(
536             proc, BitOr, Origin(),
537             argument,
538             argument));
539
540     CHECK(compileAndRun<int64_t>(proc, a) == a);
541 }
542
543 void testBitOrImms(int64_t a, int64_t b)
544 {
545     Procedure proc;
546     BasicBlock* root = proc.addBlock();
547     root->appendNew<ControlValue>(
548         proc, Return, Origin(),
549         root->appendNew<Value>(
550             proc, BitOr, Origin(),
551             root->appendNew<Const64Value>(proc, Origin(), a),
552             root->appendNew<Const64Value>(proc, Origin(), b)));
553
554     CHECK(compileAndRun<int64_t>(proc) == (a | b));
555 }
556
557 void testBitOrArgImm(int64_t a, int64_t b)
558 {
559     Procedure proc;
560     BasicBlock* root = proc.addBlock();
561     root->appendNew<ControlValue>(
562         proc, Return, Origin(),
563         root->appendNew<Value>(
564             proc, BitOr, Origin(),
565             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
566             root->appendNew<Const64Value>(proc, Origin(), b)));
567
568     CHECK(compileAndRun<int64_t>(proc, a) == (a | b));
569 }
570
571 void testBitOrImmArg(int64_t a, int64_t b)
572 {
573     Procedure proc;
574     BasicBlock* root = proc.addBlock();
575     root->appendNew<ControlValue>(
576         proc, Return, Origin(),
577         root->appendNew<Value>(
578             proc, BitOr, Origin(),
579             root->appendNew<Const64Value>(proc, Origin(), a),
580             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
581
582     CHECK(compileAndRun<int64_t>(proc, b) == (a | b));
583 }
584
585 void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c)
586 {
587     Procedure proc;
588     BasicBlock* root = proc.addBlock();
589     Value* innerBitOr = root->appendNew<Value>(
590         proc, BitOr, Origin(),
591         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
592         root->appendNew<Const64Value>(proc, Origin(), b));
593     root->appendNew<ControlValue>(
594         proc, Return, Origin(),
595         root->appendNew<Value>(
596             proc, BitOr, Origin(),
597             innerBitOr,
598             root->appendNew<Const64Value>(proc, Origin(), c)));
599
600     CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c));
601 }
602
603 void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c)
604 {
605     Procedure proc;
606     BasicBlock* root = proc.addBlock();
607     Value* innerBitOr = root->appendNew<Value>(
608         proc, BitOr, Origin(),
609         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
610         root->appendNew<Const64Value>(proc, Origin(), c));
611     root->appendNew<ControlValue>(
612         proc, Return, Origin(),
613         root->appendNew<Value>(
614             proc, BitOr, Origin(),
615             root->appendNew<Const64Value>(proc, Origin(), a),
616             innerBitOr));
617
618     CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c)));
619 }
620
621 void testBitOrArgs32(int a, int b)
622 {
623     Procedure proc;
624     BasicBlock* root = proc.addBlock();
625     root->appendNew<ControlValue>(
626         proc, Return, Origin(),
627         root->appendNew<Value>(
628             proc, BitOr, Origin(),
629             root->appendNew<Value>(
630                 proc, Trunc, Origin(),
631                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
632             root->appendNew<Value>(
633                 proc, Trunc, Origin(),
634                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
635
636     CHECK(compileAndRun<int>(proc, a, b) == (a | b));
637 }
638
639 void testBitOrSameArg32(int a)
640 {
641     Procedure proc;
642     BasicBlock* root = proc.addBlock();
643     Value* argument = root->appendNew<Value>(
644         proc, Trunc, Origin(),
645             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
646     root->appendNew<ControlValue>(
647         proc, Return, Origin(),
648         root->appendNew<Value>(
649             proc, BitOr, Origin(),
650             argument,
651             argument));
652
653     CHECK(compileAndRun<int>(proc, a) == a);
654 }
655
656 void testBitOrImms32(int a, int b)
657 {
658     Procedure proc;
659     BasicBlock* root = proc.addBlock();
660     root->appendNew<ControlValue>(
661         proc, Return, Origin(),
662         root->appendNew<Value>(
663             proc, BitOr, Origin(),
664             root->appendNew<Const32Value>(proc, Origin(), a),
665             root->appendNew<Const32Value>(proc, Origin(), b)));
666
667     CHECK(compileAndRun<int>(proc) == (a | b));
668 }
669
670 void testBitOrArgImm32(int a, int b)
671 {
672     Procedure proc;
673     BasicBlock* root = proc.addBlock();
674     root->appendNew<ControlValue>(
675         proc, Return, Origin(),
676         root->appendNew<Value>(
677             proc, BitOr, Origin(),
678             root->appendNew<Value>(
679                 proc, Trunc, Origin(),
680                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
681             root->appendNew<Const32Value>(proc, Origin(), b)));
682
683     CHECK(compileAndRun<int>(proc, a) == (a | b));
684 }
685
686 void testBitOrImmArg32(int a, int b)
687 {
688     Procedure proc;
689     BasicBlock* root = proc.addBlock();
690     root->appendNew<ControlValue>(
691         proc, Return, Origin(),
692         root->appendNew<Value>(
693             proc, BitOr, Origin(),
694             root->appendNew<Const32Value>(proc, Origin(), a),
695             root->appendNew<Value>(
696                 proc, Trunc, Origin(),
697                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
698
699     CHECK(compileAndRun<int>(proc, b) == (a | b));
700 }
701
702 void testBitOrBitOrArgImmImm32(int a, int b, int c)
703 {
704     Procedure proc;
705     BasicBlock* root = proc.addBlock();
706     Value* innerBitOr = root->appendNew<Value>(
707         proc, BitOr, Origin(),
708         root->appendNew<Value>(
709             proc, Trunc, Origin(),
710             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
711         root->appendNew<Const32Value>(proc, Origin(), b));
712     root->appendNew<ControlValue>(
713         proc, Return, Origin(),
714         root->appendNew<Value>(
715             proc, BitOr, Origin(),
716             innerBitOr,
717             root->appendNew<Const32Value>(proc, Origin(), c)));
718
719     CHECK(compileAndRun<int>(proc, a) == ((a | b) | c));
720 }
721
722 void testBitOrImmBitOrArgImm32(int a, int b, int c)
723 {
724     Procedure proc;
725     BasicBlock* root = proc.addBlock();
726     Value* innerBitOr = root->appendNew<Value>(
727         proc, BitOr, Origin(),
728         root->appendNew<Value>(
729             proc, Trunc, Origin(),
730             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
731         root->appendNew<Const32Value>(proc, Origin(), c));
732     root->appendNew<ControlValue>(
733         proc, Return, Origin(),
734         root->appendNew<Value>(
735             proc, BitOr, Origin(),
736             root->appendNew<Const32Value>(proc, Origin(), a),
737             innerBitOr));
738
739     CHECK(compileAndRun<int>(proc, b) == (a | (b | c)));
740 }
741
742 void testBitXorArgs(int64_t a, int64_t b)
743 {
744     Procedure proc;
745     BasicBlock* root = proc.addBlock();
746     root->appendNew<ControlValue>(
747         proc, Return, Origin(),
748         root->appendNew<Value>(
749             proc, BitXor, Origin(),
750             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
751             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
752
753     CHECK(compileAndRun<int64_t>(proc, a, b) == (a ^ b));
754 }
755
756 void testBitXorSameArg(int64_t a)
757 {
758     Procedure proc;
759     BasicBlock* root = proc.addBlock();
760     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
761     root->appendNew<ControlValue>(
762         proc, Return, Origin(),
763         root->appendNew<Value>(
764             proc, BitXor, Origin(),
765             argument,
766             argument));
767
768     CHECK(!compileAndRun<int64_t>(proc, a));
769 }
770
771 void testBitXorImms(int64_t a, int64_t b)
772 {
773     Procedure proc;
774     BasicBlock* root = proc.addBlock();
775     root->appendNew<ControlValue>(
776         proc, Return, Origin(),
777         root->appendNew<Value>(
778             proc, BitXor, Origin(),
779             root->appendNew<Const64Value>(proc, Origin(), a),
780             root->appendNew<Const64Value>(proc, Origin(), b)));
781
782     CHECK(compileAndRun<int64_t>(proc) == (a ^ b));
783 }
784
785 void testBitXorArgImm(int64_t a, int64_t b)
786 {
787     Procedure proc;
788     BasicBlock* root = proc.addBlock();
789     root->appendNew<ControlValue>(
790         proc, Return, Origin(),
791         root->appendNew<Value>(
792             proc, BitXor, Origin(),
793             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
794             root->appendNew<Const64Value>(proc, Origin(), b)));
795
796     CHECK(compileAndRun<int64_t>(proc, a) == (a ^ b));
797 }
798
799 void testBitXorImmArg(int64_t a, int64_t b)
800 {
801     Procedure proc;
802     BasicBlock* root = proc.addBlock();
803     root->appendNew<ControlValue>(
804         proc, Return, Origin(),
805         root->appendNew<Value>(
806             proc, BitXor, Origin(),
807             root->appendNew<Const64Value>(proc, Origin(), a),
808             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
809
810     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ b));
811 }
812
813 void testBitXorBitXorArgImmImm(int64_t a, int64_t b, int64_t c)
814 {
815     Procedure proc;
816     BasicBlock* root = proc.addBlock();
817     Value* innerBitXor = root->appendNew<Value>(
818         proc, BitXor, Origin(),
819         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
820         root->appendNew<Const64Value>(proc, Origin(), b));
821     root->appendNew<ControlValue>(
822         proc, Return, Origin(),
823         root->appendNew<Value>(
824             proc, BitXor, Origin(),
825             innerBitXor,
826             root->appendNew<Const64Value>(proc, Origin(), c)));
827
828     CHECK(compileAndRun<int64_t>(proc, a) == ((a ^ b) ^ c));
829 }
830
831 void testBitXorImmBitXorArgImm(int64_t a, int64_t b, int64_t c)
832 {
833     Procedure proc;
834     BasicBlock* root = proc.addBlock();
835     Value* innerBitXor = root->appendNew<Value>(
836         proc, BitXor, Origin(),
837         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
838         root->appendNew<Const64Value>(proc, Origin(), c));
839     root->appendNew<ControlValue>(
840         proc, Return, Origin(),
841         root->appendNew<Value>(
842             proc, BitXor, Origin(),
843             root->appendNew<Const64Value>(proc, Origin(), a),
844             innerBitXor));
845
846     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ (b ^ c)));
847 }
848
849 void testBitXorArgs32(int a, int b)
850 {
851     Procedure proc;
852     BasicBlock* root = proc.addBlock();
853     root->appendNew<ControlValue>(
854         proc, Return, Origin(),
855         root->appendNew<Value>(
856             proc, BitXor, Origin(),
857             root->appendNew<Value>(
858                 proc, Trunc, Origin(),
859                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
860             root->appendNew<Value>(
861                 proc, Trunc, Origin(),
862                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
863
864     CHECK(compileAndRun<int>(proc, a, b) == (a ^ b));
865 }
866
867 void testBitXorSameArg32(int a)
868 {
869     Procedure proc;
870     BasicBlock* root = proc.addBlock();
871     Value* argument = root->appendNew<Value>(
872         proc, Trunc, Origin(),
873             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
874     root->appendNew<ControlValue>(
875         proc, Return, Origin(),
876         root->appendNew<Value>(
877             proc, BitXor, Origin(),
878             argument,
879             argument));
880
881     CHECK(!compileAndRun<int>(proc, a));
882 }
883
884 void testBitXorImms32(int a, int b)
885 {
886     Procedure proc;
887     BasicBlock* root = proc.addBlock();
888     root->appendNew<ControlValue>(
889         proc, Return, Origin(),
890         root->appendNew<Value>(
891             proc, BitXor, Origin(),
892             root->appendNew<Const32Value>(proc, Origin(), a),
893             root->appendNew<Const32Value>(proc, Origin(), b)));
894
895     CHECK(compileAndRun<int>(proc) == (a ^ b));
896 }
897
898 void testBitXorArgImm32(int a, int b)
899 {
900     Procedure proc;
901     BasicBlock* root = proc.addBlock();
902     root->appendNew<ControlValue>(
903         proc, Return, Origin(),
904         root->appendNew<Value>(
905             proc, BitXor, Origin(),
906             root->appendNew<Value>(
907                 proc, Trunc, Origin(),
908                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
909             root->appendNew<Const32Value>(proc, Origin(), b)));
910
911     CHECK(compileAndRun<int>(proc, a) == (a ^ b));
912 }
913
914 void testBitXorImmArg32(int a, int b)
915 {
916     Procedure proc;
917     BasicBlock* root = proc.addBlock();
918     root->appendNew<ControlValue>(
919         proc, Return, Origin(),
920         root->appendNew<Value>(
921             proc, BitXor, Origin(),
922             root->appendNew<Const32Value>(proc, Origin(), a),
923             root->appendNew<Value>(
924                 proc, Trunc, Origin(),
925                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
926
927     CHECK(compileAndRun<int>(proc, b) == (a ^ b));
928 }
929
930 void testBitXorBitXorArgImmImm32(int a, int b, int c)
931 {
932     Procedure proc;
933     BasicBlock* root = proc.addBlock();
934     Value* innerBitXor = root->appendNew<Value>(
935         proc, BitXor, Origin(),
936         root->appendNew<Value>(
937             proc, Trunc, Origin(),
938             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
939         root->appendNew<Const32Value>(proc, Origin(), b));
940     root->appendNew<ControlValue>(
941         proc, Return, Origin(),
942         root->appendNew<Value>(
943             proc, BitXor, Origin(),
944             innerBitXor,
945             root->appendNew<Const32Value>(proc, Origin(), c)));
946
947     CHECK(compileAndRun<int>(proc, a) == ((a ^ b) ^ c));
948 }
949
950 void testBitXorImmBitXorArgImm32(int a, int b, int c)
951 {
952     Procedure proc;
953     BasicBlock* root = proc.addBlock();
954     Value* innerBitXor = root->appendNew<Value>(
955         proc, BitXor, Origin(),
956         root->appendNew<Value>(
957             proc, Trunc, Origin(),
958             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
959         root->appendNew<Const32Value>(proc, Origin(), c));
960     root->appendNew<ControlValue>(
961         proc, Return, Origin(),
962         root->appendNew<Value>(
963             proc, BitXor, Origin(),
964             root->appendNew<Const32Value>(proc, Origin(), a),
965             innerBitXor));
966
967     CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c)));
968 }
969
970 void testShlArgs(int64_t a, int64_t b)
971 {
972     Procedure proc;
973     BasicBlock* root = proc.addBlock();
974     root->appendNew<ControlValue>(
975         proc, Return, Origin(),
976         root->appendNew<Value>(
977             proc, Shl, Origin(),
978             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
979             root->appendNew<Value>(
980                 proc, Trunc, Origin(),
981                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
982
983     CHECK(compileAndRun<int64_t>(proc, a, b) == (a << b));
984 }
985
986 void testShlImms(int64_t a, int64_t b)
987 {
988     Procedure proc;
989     BasicBlock* root = proc.addBlock();
990     root->appendNew<ControlValue>(
991         proc, Return, Origin(),
992         root->appendNew<Value>(
993             proc, Shl, Origin(),
994             root->appendNew<Const64Value>(proc, Origin(), a),
995             root->appendNew<Const32Value>(proc, Origin(), b)));
996
997     CHECK(compileAndRun<int64_t>(proc) == (a << b));
998 }
999
1000 void testShlArgImm(int64_t a, int64_t b)
1001 {
1002     Procedure proc;
1003     BasicBlock* root = proc.addBlock();
1004     root->appendNew<ControlValue>(
1005         proc, Return, Origin(),
1006         root->appendNew<Value>(
1007             proc, Shl, Origin(),
1008             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1009             root->appendNew<Const32Value>(proc, Origin(), b)));
1010
1011     CHECK(compileAndRun<int64_t>(proc, a) == (a << b));
1012 }
1013
1014 void testShlArgs32(int32_t a, int32_t b)
1015 {
1016     Procedure proc;
1017     BasicBlock* root = proc.addBlock();
1018     root->appendNew<ControlValue>(
1019         proc, Return, Origin(),
1020         root->appendNew<Value>(
1021             proc, Shl, Origin(),
1022             root->appendNew<Value>(
1023                 proc, Trunc, Origin(),
1024                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1025             root->appendNew<Value>(
1026                 proc, Trunc, Origin(),
1027                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1028
1029     CHECK(compileAndRun<int32_t>(proc, a, b) == (a << b));
1030 }
1031
1032 void testShlImms32(int32_t a, int32_t b)
1033 {
1034     Procedure proc;
1035     BasicBlock* root = proc.addBlock();
1036     root->appendNew<ControlValue>(
1037         proc, Return, Origin(),
1038         root->appendNew<Value>(
1039             proc, Shl, Origin(),
1040             root->appendNew<Const32Value>(proc, Origin(), a),
1041             root->appendNew<Const32Value>(proc, Origin(), b)));
1042
1043     CHECK(compileAndRun<int32_t>(proc) == (a << b));
1044 }
1045
1046 void testShlArgImm32(int32_t a, int32_t b)
1047 {
1048     Procedure proc;
1049     BasicBlock* root = proc.addBlock();
1050     root->appendNew<ControlValue>(
1051         proc, Return, Origin(),
1052         root->appendNew<Value>(
1053             proc, Shl, Origin(),
1054             root->appendNew<Value>(
1055                 proc, Trunc, Origin(),
1056                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1057             root->appendNew<Const32Value>(proc, Origin(), b)));
1058
1059     CHECK(compileAndRun<int32_t>(proc, a) == (a << b));
1060 }
1061
1062 void testSShrArgs(int64_t a, int64_t b)
1063 {
1064     Procedure proc;
1065     BasicBlock* root = proc.addBlock();
1066     root->appendNew<ControlValue>(
1067         proc, Return, Origin(),
1068         root->appendNew<Value>(
1069             proc, SShr, Origin(),
1070             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1071             root->appendNew<Value>(
1072                 proc, Trunc, Origin(),
1073                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1074
1075     CHECK(compileAndRun<int64_t>(proc, a, b) == (a >> b));
1076 }
1077
1078 void testSShrImms(int64_t a, int64_t b)
1079 {
1080     Procedure proc;
1081     BasicBlock* root = proc.addBlock();
1082     root->appendNew<ControlValue>(
1083         proc, Return, Origin(),
1084         root->appendNew<Value>(
1085             proc, SShr, Origin(),
1086             root->appendNew<Const64Value>(proc, Origin(), a),
1087             root->appendNew<Const32Value>(proc, Origin(), b)));
1088
1089     CHECK(compileAndRun<int64_t>(proc) == (a >> b));
1090 }
1091
1092 void testSShrArgImm(int64_t a, int64_t b)
1093 {
1094     Procedure proc;
1095     BasicBlock* root = proc.addBlock();
1096     root->appendNew<ControlValue>(
1097         proc, Return, Origin(),
1098         root->appendNew<Value>(
1099             proc, SShr, Origin(),
1100             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1101             root->appendNew<Const32Value>(proc, Origin(), b)));
1102
1103     CHECK(compileAndRun<int64_t>(proc, a) == (a >> b));
1104 }
1105
1106 void testSShrArgs32(int32_t a, int32_t b)
1107 {
1108     Procedure proc;
1109     BasicBlock* root = proc.addBlock();
1110     root->appendNew<ControlValue>(
1111         proc, Return, Origin(),
1112         root->appendNew<Value>(
1113             proc, SShr, Origin(),
1114             root->appendNew<Value>(
1115                 proc, Trunc, Origin(),
1116                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1117             root->appendNew<Value>(
1118                 proc, Trunc, Origin(),
1119                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1120
1121     CHECK(compileAndRun<int32_t>(proc, a, b) == (a >> b));
1122 }
1123
1124 void testSShrImms32(int32_t a, int32_t b)
1125 {
1126     Procedure proc;
1127     BasicBlock* root = proc.addBlock();
1128     root->appendNew<ControlValue>(
1129         proc, Return, Origin(),
1130         root->appendNew<Value>(
1131             proc, SShr, Origin(),
1132             root->appendNew<Const32Value>(proc, Origin(), a),
1133             root->appendNew<Const32Value>(proc, Origin(), b)));
1134
1135     CHECK(compileAndRun<int32_t>(proc) == (a >> b));
1136 }
1137
1138 void testSShrArgImm32(int32_t a, int32_t b)
1139 {
1140     Procedure proc;
1141     BasicBlock* root = proc.addBlock();
1142     root->appendNew<ControlValue>(
1143         proc, Return, Origin(),
1144         root->appendNew<Value>(
1145             proc, SShr, Origin(),
1146             root->appendNew<Value>(
1147                 proc, Trunc, Origin(),
1148                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1149             root->appendNew<Const32Value>(proc, Origin(), b)));
1150
1151     CHECK(compileAndRun<int32_t>(proc, a) == (a >> b));
1152 }
1153
1154 void testZShrArgs(uint64_t a, uint64_t b)
1155 {
1156     Procedure proc;
1157     BasicBlock* root = proc.addBlock();
1158     root->appendNew<ControlValue>(
1159         proc, Return, Origin(),
1160         root->appendNew<Value>(
1161             proc, ZShr, Origin(),
1162             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1163             root->appendNew<Value>(
1164                 proc, Trunc, Origin(),
1165                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1166
1167     CHECK(compileAndRun<uint64_t>(proc, a, b) == (a >> b));
1168 }
1169
1170 void testZShrImms(uint64_t a, uint64_t b)
1171 {
1172     Procedure proc;
1173     BasicBlock* root = proc.addBlock();
1174     root->appendNew<ControlValue>(
1175         proc, Return, Origin(),
1176         root->appendNew<Value>(
1177             proc, ZShr, Origin(),
1178             root->appendNew<Const64Value>(proc, Origin(), a),
1179             root->appendNew<Const32Value>(proc, Origin(), b)));
1180
1181     CHECK(compileAndRun<uint64_t>(proc) == (a >> b));
1182 }
1183
1184 void testZShrArgImm(uint64_t a, uint64_t b)
1185 {
1186     Procedure proc;
1187     BasicBlock* root = proc.addBlock();
1188     root->appendNew<ControlValue>(
1189         proc, Return, Origin(),
1190         root->appendNew<Value>(
1191             proc, ZShr, Origin(),
1192             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1193             root->appendNew<Const32Value>(proc, Origin(), b)));
1194
1195     CHECK(compileAndRun<uint64_t>(proc, a) == (a >> b));
1196 }
1197
1198 void testZShrArgs32(uint32_t a, uint32_t b)
1199 {
1200     Procedure proc;
1201     BasicBlock* root = proc.addBlock();
1202     root->appendNew<ControlValue>(
1203         proc, Return, Origin(),
1204         root->appendNew<Value>(
1205             proc, ZShr, Origin(),
1206             root->appendNew<Value>(
1207                 proc, Trunc, Origin(),
1208                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1209             root->appendNew<Value>(
1210                 proc, Trunc, Origin(),
1211                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1212
1213     CHECK(compileAndRun<uint32_t>(proc, a, b) == (a >> b));
1214 }
1215
1216 void testZShrImms32(uint32_t a, uint32_t b)
1217 {
1218     Procedure proc;
1219     BasicBlock* root = proc.addBlock();
1220     root->appendNew<ControlValue>(
1221         proc, Return, Origin(),
1222         root->appendNew<Value>(
1223             proc, ZShr, Origin(),
1224             root->appendNew<Const32Value>(proc, Origin(), a),
1225             root->appendNew<Const32Value>(proc, Origin(), b)));
1226
1227     CHECK(compileAndRun<uint32_t>(proc) == (a >> b));
1228 }
1229
1230 void testZShrArgImm32(uint32_t a, uint32_t b)
1231 {
1232     Procedure proc;
1233     BasicBlock* root = proc.addBlock();
1234     root->appendNew<ControlValue>(
1235         proc, Return, Origin(),
1236         root->appendNew<Value>(
1237             proc, ZShr, Origin(),
1238             root->appendNew<Value>(
1239                 proc, Trunc, Origin(),
1240                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1241             root->appendNew<Const32Value>(proc, Origin(), b)));
1242
1243     CHECK(compileAndRun<uint32_t>(proc, a) == (a >> b));
1244 }
1245
1246 void testStore(int value)
1247 {
1248     Procedure proc;
1249     BasicBlock* root = proc.addBlock();
1250     int slot = 0xbaadbeef;
1251     root->appendNew<MemoryValue>(
1252         proc, Store, Origin(),
1253         root->appendNew<Value>(
1254             proc, Trunc, Origin(),
1255             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1256         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
1257     root->appendNew<ControlValue>(
1258         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1259
1260     CHECK(!compileAndRun<int>(proc, value));
1261     CHECK(slot == value);
1262 }
1263
1264 void testStoreConstant(int value)
1265 {
1266     Procedure proc;
1267     BasicBlock* root = proc.addBlock();
1268     int slot = 0xbaadbeef;
1269     root->appendNew<MemoryValue>(
1270         proc, Store, Origin(),
1271         root->appendNew<Const32Value>(proc, Origin(), value),
1272         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
1273     root->appendNew<ControlValue>(
1274         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1275
1276     CHECK(!compileAndRun<int>(proc));
1277     CHECK(slot == value);
1278 }
1279
1280 void testStoreConstantPtr(intptr_t value)
1281 {
1282     Procedure proc;
1283     BasicBlock* root = proc.addBlock();
1284     intptr_t slot;
1285     if (is64Bit())
1286         slot = (static_cast<intptr_t>(0xbaadbeef) << 32) + static_cast<intptr_t>(0xbaadbeef);
1287     else
1288         slot = 0xbaadbeef;
1289     root->appendNew<MemoryValue>(
1290         proc, Store, Origin(),
1291         root->appendNew<ConstPtrValue>(proc, Origin(), value),
1292         root->appendNew<ConstPtrValue>(proc, Origin(), &slot));
1293     root->appendNew<ControlValue>(
1294         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1295
1296     CHECK(!compileAndRun<int>(proc));
1297     CHECK(slot == value);
1298 }
1299
1300 void testTrunc(int64_t value)
1301 {
1302     Procedure proc;
1303     BasicBlock* root = proc.addBlock();
1304     root->appendNew<ControlValue>(
1305         proc, Return, Origin(),
1306         root->appendNew<Value>(
1307             proc, Trunc, Origin(),
1308             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1309
1310     CHECK(compileAndRun<int>(proc, value) == static_cast<int>(value));
1311 }
1312
1313 void testAdd1(int value)
1314 {
1315     Procedure proc;
1316     BasicBlock* root = proc.addBlock();
1317     root->appendNew<ControlValue>(
1318         proc, Return, Origin(),
1319         root->appendNew<Value>(
1320             proc, Add, Origin(),
1321             root->appendNew<Value>(
1322                 proc, Trunc, Origin(),
1323                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1324             root->appendNew<Const32Value>(proc, Origin(), 1)));
1325
1326     CHECK(compileAndRun<int>(proc, value) == value + 1);
1327 }
1328
1329 void testAdd1Ptr(intptr_t value)
1330 {
1331     Procedure proc;
1332     BasicBlock* root = proc.addBlock();
1333     root->appendNew<ControlValue>(
1334         proc, Return, Origin(),
1335         root->appendNew<Value>(
1336             proc, Add, Origin(),
1337             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1338             root->appendNew<ConstPtrValue>(proc, Origin(), 1)));
1339
1340     CHECK(compileAndRun<intptr_t>(proc, value) == value + 1);
1341 }
1342
1343 void testNeg32(int32_t value)
1344 {
1345     Procedure proc;
1346     BasicBlock* root = proc.addBlock();
1347     root->appendNew<ControlValue>(
1348         proc, Return, Origin(),
1349         root->appendNew<Value>(
1350             proc, Sub, Origin(),
1351             root->appendNew<Const32Value>(proc, Origin(), 0),
1352             root->appendNew<Value>(
1353                 proc, Trunc, Origin(),
1354                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
1355
1356     CHECK(compileAndRun<int32_t>(proc, value) == -value);
1357 }
1358
1359 void testNegPtr(intptr_t value)
1360 {
1361     Procedure proc;
1362     BasicBlock* root = proc.addBlock();
1363     root->appendNew<ControlValue>(
1364         proc, Return, Origin(),
1365         root->appendNew<Value>(
1366             proc, Sub, Origin(),
1367             root->appendNew<ConstPtrValue>(proc, Origin(), 0),
1368             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1369
1370     CHECK(compileAndRun<intptr_t>(proc, value) == -value);
1371 }
1372
1373 void testStoreAddLoad(int amount)
1374 {
1375     Procedure proc;
1376     BasicBlock* root = proc.addBlock();
1377     int slot = 37;
1378     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
1379     root->appendNew<MemoryValue>(
1380         proc, Store, Origin(),
1381         root->appendNew<Value>(
1382             proc, Add, Origin(),
1383             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
1384             root->appendNew<Const32Value>(proc, Origin(), amount)),
1385         slotPtr);
1386     root->appendNew<ControlValue>(
1387         proc, Return, Origin(),
1388         root->appendNew<Const32Value>(proc, Origin(), 0));
1389
1390     CHECK(!compileAndRun<int>(proc));
1391     CHECK(slot == 37 + amount);
1392 }
1393
1394 void testStoreSubLoad(int amount)
1395 {
1396     Procedure proc;
1397     BasicBlock* root = proc.addBlock();
1398     int32_t startValue = std::numeric_limits<int32_t>::min();
1399     int32_t slot = startValue;
1400     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
1401     root->appendNew<MemoryValue>(
1402         proc, Store, Origin(),
1403         root->appendNew<Value>(
1404             proc, Sub, Origin(),
1405             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
1406             root->appendNew<Value>(
1407                 proc, Trunc, Origin(),
1408                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
1409         slotPtr);
1410     root->appendNew<ControlValue>(
1411         proc, Return, Origin(),
1412         root->appendNew<Const32Value>(proc, Origin(), 0));
1413
1414     CHECK(!compileAndRun<int>(proc, amount));
1415     CHECK(slot == startValue - amount);
1416 }
1417
1418 void testStoreAddLoadInterference(int amount)
1419 {
1420     Procedure proc;
1421     BasicBlock* root = proc.addBlock();
1422     int slot = 37;
1423     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
1424     ArgumentRegValue* otherSlotPtr =
1425         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1426     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr);
1427     root->appendNew<MemoryValue>(
1428         proc, Store, Origin(),
1429         root->appendNew<Const32Value>(proc, Origin(), 666),
1430         otherSlotPtr);
1431     root->appendNew<MemoryValue>(
1432         proc, Store, Origin(),
1433         root->appendNew<Value>(
1434             proc, Add, Origin(),
1435             load, root->appendNew<Const32Value>(proc, Origin(), amount)),
1436         slotPtr);
1437     root->appendNew<ControlValue>(
1438         proc, Return, Origin(),
1439         root->appendNew<Const32Value>(proc, Origin(), 0));
1440
1441     CHECK(!compileAndRun<int>(proc, &slot));
1442     CHECK(slot == 37 + amount);
1443 }
1444
1445 void testStoreAddAndLoad(int amount, int mask)
1446 {
1447     Procedure proc;
1448     BasicBlock* root = proc.addBlock();
1449     int slot = 37;
1450     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
1451     root->appendNew<MemoryValue>(
1452         proc, Store, Origin(),
1453         root->appendNew<Value>(
1454             proc, BitAnd, Origin(),
1455             root->appendNew<Value>(
1456                 proc, Add, Origin(),
1457                 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
1458                 root->appendNew<Const32Value>(proc, Origin(), amount)),
1459             root->appendNew<Const32Value>(proc, Origin(), mask)),
1460         slotPtr);
1461     root->appendNew<ControlValue>(
1462         proc, Return, Origin(),
1463         root->appendNew<Const32Value>(proc, Origin(), 0));
1464
1465     CHECK(!compileAndRun<int>(proc));
1466     CHECK(slot == ((37 + amount) & mask));
1467 }
1468
1469 void testStoreNegLoad32(int32_t value)
1470 {
1471     Procedure proc;
1472     BasicBlock* root = proc.addBlock();
1473
1474     int32_t slot = value;
1475
1476     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
1477     
1478     root->appendNew<MemoryValue>(
1479         proc, Store, Origin(),
1480         root->appendNew<Value>(
1481             proc, Sub, Origin(),
1482             root->appendNew<Const32Value>(proc, Origin(), 0),
1483             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)),
1484         slotPtr);
1485     
1486     root->appendNew<ControlValue>(
1487         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1488
1489     CHECK(!compileAndRun<int32_t>(proc));
1490     CHECK(slot == -value);
1491 }
1492
1493 void testStoreNegLoadPtr(intptr_t value)
1494 {
1495     Procedure proc;
1496     BasicBlock* root = proc.addBlock();
1497
1498     intptr_t slot = value;
1499
1500     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
1501     
1502     root->appendNew<MemoryValue>(
1503         proc, Store, Origin(),
1504         root->appendNew<Value>(
1505             proc, Sub, Origin(),
1506             root->appendNew<ConstPtrValue>(proc, Origin(), 0),
1507             root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)),
1508         slotPtr);
1509     
1510     root->appendNew<ControlValue>(
1511         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1512
1513     CHECK(!compileAndRun<int32_t>(proc));
1514     CHECK(slot == -value);
1515 }
1516
1517 void testAdd1Uncommuted(int value)
1518 {
1519     Procedure proc;
1520     BasicBlock* root = proc.addBlock();
1521     root->appendNew<ControlValue>(
1522         proc, Return, Origin(),
1523         root->appendNew<Value>(
1524             proc, Add, Origin(),
1525             root->appendNew<Const32Value>(proc, Origin(), 1),
1526             root->appendNew<Value>(
1527                 proc, Trunc, Origin(),
1528                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
1529
1530     CHECK(compileAndRun<int>(proc, value) == value + 1);
1531 }
1532
1533 void testLoadOffset()
1534 {
1535     Procedure proc;
1536     BasicBlock* root = proc.addBlock();
1537     int array[] = { 1, 2 };
1538     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
1539     root->appendNew<ControlValue>(
1540         proc, Return, Origin(),
1541         root->appendNew<Value>(
1542             proc, Add, Origin(),
1543             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
1544             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int))));
1545
1546     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
1547 }
1548
1549 void testLoadOffsetNotConstant()
1550 {
1551     Procedure proc;
1552     BasicBlock* root = proc.addBlock();
1553     int array[] = { 1, 2 };
1554     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1555     root->appendNew<ControlValue>(
1556         proc, Return, Origin(),
1557         root->appendNew<Value>(
1558             proc, Add, Origin(),
1559             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
1560             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int))));
1561
1562     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
1563 }
1564
1565 void testLoadOffsetUsingAdd()
1566 {
1567     Procedure proc;
1568     BasicBlock* root = proc.addBlock();
1569     int array[] = { 1, 2 };
1570     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
1571     root->appendNew<ControlValue>(
1572         proc, Return, Origin(),
1573         root->appendNew<Value>(
1574             proc, Add, Origin(),
1575             root->appendNew<MemoryValue>(
1576                 proc, Load, Int32, Origin(),
1577                 root->appendNew<Value>(
1578                     proc, Add, Origin(), arrayPtr,
1579                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
1580             root->appendNew<MemoryValue>(
1581                 proc, Load, Int32, Origin(),
1582                 root->appendNew<Value>(
1583                     proc, Add, Origin(), arrayPtr,
1584                     root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
1585     
1586     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
1587 }
1588
1589 void testLoadOffsetUsingAddInterference()
1590 {
1591     Procedure proc;
1592     BasicBlock* root = proc.addBlock();
1593     int array[] = { 1, 2 };
1594     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
1595     ArgumentRegValue* otherArrayPtr =
1596         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1597     Const32Value* theNumberOfTheBeast = root->appendNew<Const32Value>(proc, Origin(), 666);
1598     MemoryValue* left = root->appendNew<MemoryValue>(
1599         proc, Load, Int32, Origin(),
1600         root->appendNew<Value>(
1601             proc, Add, Origin(), arrayPtr,
1602             root->appendNew<ConstPtrValue>(proc, Origin(), 0)));
1603     MemoryValue* right = root->appendNew<MemoryValue>(
1604         proc, Load, Int32, Origin(),
1605         root->appendNew<Value>(
1606             proc, Add, Origin(), arrayPtr,
1607             root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))));
1608     root->appendNew<MemoryValue>(
1609         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0);
1610     root->appendNew<MemoryValue>(
1611         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, sizeof(int));
1612     root->appendNew<ControlValue>(
1613         proc, Return, Origin(),
1614         root->appendNew<Value>(
1615             proc, Add, Origin(), left, right));
1616     
1617     CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2);
1618     CHECK(array[0] == 666);
1619     CHECK(array[1] == 666);
1620 }
1621
1622 void testLoadOffsetUsingAddNotConstant()
1623 {
1624     Procedure proc;
1625     BasicBlock* root = proc.addBlock();
1626     int array[] = { 1, 2 };
1627     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1628     root->appendNew<ControlValue>(
1629         proc, Return, Origin(),
1630         root->appendNew<Value>(
1631             proc, Add, Origin(),
1632             root->appendNew<MemoryValue>(
1633                 proc, Load, Int32, Origin(),
1634                 root->appendNew<Value>(
1635                     proc, Add, Origin(), arrayPtr,
1636                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
1637             root->appendNew<MemoryValue>(
1638                 proc, Load, Int32, Origin(),
1639                 root->appendNew<Value>(
1640                     proc, Add, Origin(), arrayPtr,
1641                     root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
1642     
1643     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
1644 }
1645
1646 void testFramePointer()
1647 {
1648     Procedure proc;
1649     BasicBlock* root = proc.addBlock();
1650     root->appendNew<ControlValue>(
1651         proc, Return, Origin(),
1652         root->appendNew<Value>(proc, FramePointer, Origin()));
1653
1654     void* fp = compileAndRun<void*>(proc);
1655     CHECK(fp < &proc);
1656     CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
1657 }
1658
1659 void testStackSlot()
1660 {
1661     Procedure proc;
1662     BasicBlock* root = proc.addBlock();
1663     root->appendNew<ControlValue>(
1664         proc, Return, Origin(),
1665         root->appendNew<StackSlotValue>(proc, Origin(), 1, StackSlotKind::Anonymous));
1666
1667     void* stackSlot = compileAndRun<void*>(proc);
1668     CHECK(stackSlot < &proc);
1669     CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000);
1670 }
1671
1672 void testLoadFromFramePointer()
1673 {
1674     Procedure proc;
1675     BasicBlock* root = proc.addBlock();
1676     root->appendNew<ControlValue>(
1677         proc, Return, Origin(),
1678         root->appendNew<MemoryValue>(
1679             proc, Load, pointerType(), Origin(),
1680             root->appendNew<Value>(proc, FramePointer, Origin())));
1681
1682     void* fp = compileAndRun<void*>(proc);
1683     void* myFP = __builtin_frame_address(0);
1684     CHECK(fp <= myFP);
1685     CHECK(fp >= bitwise_cast<char*>(myFP) - 10000);
1686 }
1687
1688 void testStoreLoadStackSlot(int value)
1689 {
1690     Procedure proc;
1691     BasicBlock* root = proc.addBlock();
1692
1693     StackSlotValue* stack = root->appendNew<StackSlotValue>(
1694         proc, Origin(), sizeof(int), StackSlotKind::Anonymous);
1695
1696     root->appendNew<MemoryValue>(
1697         proc, Store, Origin(),
1698         root->appendNew<Value>(
1699             proc, Trunc, Origin(),
1700             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1701         stack);
1702     
1703     root->appendNew<ControlValue>(
1704         proc, Return, Origin(),
1705         root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack));
1706
1707     CHECK(compileAndRun<int>(proc, value) == value);
1708 }
1709
1710 template<typename T>
1711 int32_t modelLoad(int32_t value)
1712 {
1713     union {
1714         int32_t original;
1715         T loaded;
1716     } u;
1717
1718     u.original = value;
1719     if (std::is_signed<T>::value)
1720         return static_cast<int32_t>(u.loaded);
1721     return static_cast<int32_t>(static_cast<uint32_t>(u.loaded));
1722 }
1723
1724 template<typename T>
1725 void testLoad(B3::Opcode opcode, int32_t value)
1726 {
1727     // Simple load from an absolute address.
1728     {
1729         Procedure proc;
1730         BasicBlock* root = proc.addBlock();
1731         
1732         root->appendNew<ControlValue>(
1733             proc, Return, Origin(),
1734             root->appendNew<MemoryValue>(
1735                 proc, opcode, Int32, Origin(),
1736                 root->appendNew<ConstPtrValue>(proc, Origin(), &value)));
1737
1738         CHECK(compileAndRun<int32_t>(proc) == modelLoad<T>(value));
1739     }
1740     
1741     // Simple load from an address in a register.
1742     {
1743         Procedure proc;
1744         BasicBlock* root = proc.addBlock();
1745         
1746         root->appendNew<ControlValue>(
1747             proc, Return, Origin(),
1748             root->appendNew<MemoryValue>(
1749                 proc, opcode, Int32, Origin(),
1750                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1751
1752         CHECK(compileAndRun<int32_t>(proc, &value) == modelLoad<T>(value));
1753     }
1754     
1755     // Simple load from an address in a register, at an offset.
1756     {
1757         Procedure proc;
1758         BasicBlock* root = proc.addBlock();
1759         
1760         root->appendNew<ControlValue>(
1761             proc, Return, Origin(),
1762             root->appendNew<MemoryValue>(
1763                 proc, opcode, Int32, Origin(),
1764                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1765                 sizeof(int32_t)));
1766
1767         CHECK(compileAndRun<int32_t>(proc, &value - 1) == modelLoad<T>(value));
1768     }
1769
1770     // Load from a simple base-index with various scales.
1771     for (unsigned logScale = 0; logScale <= 3; ++logScale) {
1772         Procedure proc;
1773         BasicBlock* root = proc.addBlock();
1774
1775         root->appendNew<ControlValue>(
1776             proc, Return, Origin(),
1777             root->appendNew<MemoryValue>(
1778                 proc, opcode, Int32, Origin(),
1779                 root->appendNew<Value>(
1780                     proc, Add, Origin(),
1781                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1782                     root->appendNew<Value>(
1783                         proc, Shl, Origin(),
1784                         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
1785                         root->appendNew<Const32Value>(proc, Origin(), logScale)))));
1786
1787         CHECK(compileAndRun<int32_t>(proc, &value - 2, (sizeof(int32_t) * 2) >> logScale) == modelLoad<T>(value));
1788     }
1789
1790     // Load from a simple base-index with various scales, but commuted.
1791     for (unsigned logScale = 0; logScale <= 3; ++logScale) {
1792         Procedure proc;
1793         BasicBlock* root = proc.addBlock();
1794
1795         root->appendNew<ControlValue>(
1796             proc, Return, Origin(),
1797             root->appendNew<MemoryValue>(
1798                 proc, opcode, Int32, Origin(),
1799                 root->appendNew<Value>(
1800                     proc, Add, Origin(),
1801                     root->appendNew<Value>(
1802                         proc, Shl, Origin(),
1803                         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
1804                         root->appendNew<Const32Value>(proc, Origin(), logScale)),
1805                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
1806
1807         CHECK(compileAndRun<int32_t>(proc, &value - 2, (sizeof(int32_t) * 2) >> logScale) == modelLoad<T>(value));
1808     }
1809 }
1810
1811 void testBranch()
1812 {
1813     Procedure proc;
1814     BasicBlock* root = proc.addBlock();
1815     BasicBlock* thenCase = proc.addBlock();
1816     BasicBlock* elseCase = proc.addBlock();
1817
1818     root->appendNew<ControlValue>(
1819         proc, Branch, Origin(),
1820         root->appendNew<Value>(
1821             proc, Trunc, Origin(),
1822             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1823         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1824
1825     thenCase->appendNew<ControlValue>(
1826         proc, Return, Origin(),
1827         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1828
1829     elseCase->appendNew<ControlValue>(
1830         proc, Return, Origin(),
1831         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1832
1833     auto code = compile(proc);
1834     CHECK(invoke<int>(*code, 42) == 1);
1835     CHECK(invoke<int>(*code, 0) == 0);
1836 }
1837
1838 void testBranchPtr()
1839 {
1840     Procedure proc;
1841     BasicBlock* root = proc.addBlock();
1842     BasicBlock* thenCase = proc.addBlock();
1843     BasicBlock* elseCase = proc.addBlock();
1844
1845     root->appendNew<ControlValue>(
1846         proc, Branch, Origin(),
1847         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1848         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1849
1850     thenCase->appendNew<ControlValue>(
1851         proc, Return, Origin(),
1852         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1853
1854     elseCase->appendNew<ControlValue>(
1855         proc, Return, Origin(),
1856         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1857
1858     auto code = compile(proc);
1859     CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1);
1860     CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0);
1861 }
1862
1863 void testDiamond()
1864 {
1865     Procedure proc;
1866     BasicBlock* root = proc.addBlock();
1867     BasicBlock* thenCase = proc.addBlock();
1868     BasicBlock* elseCase = proc.addBlock();
1869     BasicBlock* done = proc.addBlock();
1870
1871     root->appendNew<ControlValue>(
1872         proc, Branch, Origin(),
1873         root->appendNew<Value>(
1874             proc, Trunc, Origin(),
1875             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1876         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1877
1878     UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
1879         proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1880     thenCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
1881
1882     UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
1883         proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1884     elseCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
1885
1886     Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
1887     thenResult->setPhi(phi);
1888     elseResult->setPhi(phi);
1889     done->appendNew<ControlValue>(proc, Return, Origin(), phi);
1890
1891     auto code = compile(proc);
1892     CHECK(invoke<int>(*code, 42) == 1);
1893     CHECK(invoke<int>(*code, 0) == 0);
1894 }
1895
1896 void testBranchNotEqual()
1897 {
1898     Procedure proc;
1899     BasicBlock* root = proc.addBlock();
1900     BasicBlock* thenCase = proc.addBlock();
1901     BasicBlock* elseCase = proc.addBlock();
1902
1903     root->appendNew<ControlValue>(
1904         proc, Branch, Origin(),
1905         root->appendNew<Value>(
1906             proc, NotEqual, Origin(),
1907             root->appendNew<Value>(
1908                 proc, Trunc, Origin(),
1909                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1910             root->appendNew<Const32Value>(proc, Origin(), 0)),
1911         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1912
1913     thenCase->appendNew<ControlValue>(
1914         proc, Return, Origin(),
1915         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1916
1917     elseCase->appendNew<ControlValue>(
1918         proc, Return, Origin(),
1919         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1920
1921     auto code = compile(proc);
1922     CHECK(invoke<int>(*code, 42) == 1);
1923     CHECK(invoke<int>(*code, 0) == 0);
1924 }
1925
1926 void testBranchNotEqualCommute()
1927 {
1928     Procedure proc;
1929     BasicBlock* root = proc.addBlock();
1930     BasicBlock* thenCase = proc.addBlock();
1931     BasicBlock* elseCase = proc.addBlock();
1932
1933     root->appendNew<ControlValue>(
1934         proc, Branch, Origin(),
1935         root->appendNew<Value>(
1936             proc, NotEqual, Origin(),
1937             root->appendNew<Const32Value>(proc, Origin(), 0),
1938             root->appendNew<Value>(
1939                 proc, Trunc, Origin(),
1940                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
1941         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1942
1943     thenCase->appendNew<ControlValue>(
1944         proc, Return, Origin(),
1945         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1946
1947     elseCase->appendNew<ControlValue>(
1948         proc, Return, Origin(),
1949         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1950
1951     auto code = compile(proc);
1952     CHECK(invoke<int>(*code, 42) == 1);
1953     CHECK(invoke<int>(*code, 0) == 0);
1954 }
1955
1956 void testBranchNotEqualNotEqual()
1957 {
1958     Procedure proc;
1959     BasicBlock* root = proc.addBlock();
1960     BasicBlock* thenCase = proc.addBlock();
1961     BasicBlock* elseCase = proc.addBlock();
1962
1963     root->appendNew<ControlValue>(
1964         proc, Branch, Origin(),
1965         root->appendNew<Value>(
1966             proc, NotEqual, Origin(),
1967             root->appendNew<Value>(
1968                 proc, NotEqual, Origin(),
1969                 root->appendNew<Value>(
1970                     proc, Trunc, Origin(),
1971                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1972                 root->appendNew<Const32Value>(proc, Origin(), 0)),
1973             root->appendNew<Const32Value>(proc, Origin(), 0)),
1974         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1975
1976     thenCase->appendNew<ControlValue>(
1977         proc, Return, Origin(),
1978         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1979
1980     elseCase->appendNew<ControlValue>(
1981         proc, Return, Origin(),
1982         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1983
1984     auto code = compile(proc);
1985     CHECK(invoke<int>(*code, 42) == 1);
1986     CHECK(invoke<int>(*code, 0) == 0);
1987 }
1988
1989 void testBranchEqual()
1990 {
1991     Procedure proc;
1992     BasicBlock* root = proc.addBlock();
1993     BasicBlock* thenCase = proc.addBlock();
1994     BasicBlock* elseCase = proc.addBlock();
1995
1996     root->appendNew<ControlValue>(
1997         proc, Branch, Origin(),
1998         root->appendNew<Value>(
1999             proc, Equal, Origin(),
2000             root->appendNew<Value>(
2001                 proc, Trunc, Origin(),
2002                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2003             root->appendNew<Const32Value>(proc, Origin(), 0)),
2004         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2005
2006     thenCase->appendNew<ControlValue>(
2007         proc, Return, Origin(),
2008         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
2009
2010     elseCase->appendNew<ControlValue>(
2011         proc, Return, Origin(),
2012         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
2013
2014     auto code = compile(proc);
2015     CHECK(invoke<int>(*code, 42) == 1);
2016     CHECK(invoke<int>(*code, 0) == 0);
2017 }
2018
2019 void testBranchEqualEqual()
2020 {
2021     Procedure proc;
2022     BasicBlock* root = proc.addBlock();
2023     BasicBlock* thenCase = proc.addBlock();
2024     BasicBlock* elseCase = proc.addBlock();
2025
2026     root->appendNew<ControlValue>(
2027         proc, Branch, Origin(),
2028         root->appendNew<Value>(
2029             proc, Equal, Origin(),
2030             root->appendNew<Value>(
2031                 proc, Equal, Origin(),
2032                 root->appendNew<Value>(
2033                     proc, Trunc, Origin(),
2034                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2035                 root->appendNew<Const32Value>(proc, Origin(), 0)),
2036             root->appendNew<Const32Value>(proc, Origin(), 0)),
2037         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2038
2039     thenCase->appendNew<ControlValue>(
2040         proc, Return, Origin(),
2041         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2042
2043     elseCase->appendNew<ControlValue>(
2044         proc, Return, Origin(),
2045         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2046
2047     auto code = compile(proc);
2048     CHECK(invoke<int>(*code, 42) == 1);
2049     CHECK(invoke<int>(*code, 0) == 0);
2050 }
2051
2052 void testBranchEqualCommute()
2053 {
2054     Procedure proc;
2055     BasicBlock* root = proc.addBlock();
2056     BasicBlock* thenCase = proc.addBlock();
2057     BasicBlock* elseCase = proc.addBlock();
2058
2059     root->appendNew<ControlValue>(
2060         proc, Branch, Origin(),
2061         root->appendNew<Value>(
2062             proc, Equal, Origin(),
2063             root->appendNew<Const32Value>(proc, Origin(), 0),
2064             root->appendNew<Value>(
2065                 proc, Trunc, Origin(),
2066                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
2067         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2068
2069     thenCase->appendNew<ControlValue>(
2070         proc, Return, Origin(),
2071         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
2072
2073     elseCase->appendNew<ControlValue>(
2074         proc, Return, Origin(),
2075         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
2076
2077     auto code = compile(proc);
2078     CHECK(invoke<int>(*code, 42) == 1);
2079     CHECK(invoke<int>(*code, 0) == 0);
2080 }
2081
2082 void testBranchEqualEqual1()
2083 {
2084     Procedure proc;
2085     BasicBlock* root = proc.addBlock();
2086     BasicBlock* thenCase = proc.addBlock();
2087     BasicBlock* elseCase = proc.addBlock();
2088
2089     root->appendNew<ControlValue>(
2090         proc, Branch, Origin(),
2091         root->appendNew<Value>(
2092             proc, Equal, Origin(),
2093             root->appendNew<Value>(
2094                 proc, Equal, Origin(),
2095                 root->appendNew<Value>(
2096                     proc, Trunc, Origin(),
2097                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2098                 root->appendNew<Const32Value>(proc, Origin(), 0)),
2099             root->appendNew<Const32Value>(proc, Origin(), 1)),
2100         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2101
2102     thenCase->appendNew<ControlValue>(
2103         proc, Return, Origin(),
2104         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
2105
2106     elseCase->appendNew<ControlValue>(
2107         proc, Return, Origin(),
2108         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
2109
2110     auto code = compile(proc);
2111     CHECK(invoke<int>(*code, 42) == 1);
2112     CHECK(invoke<int>(*code, 0) == 0);
2113 }
2114
2115 void testBranchFold(int value)
2116 {
2117     Procedure proc;
2118     BasicBlock* root = proc.addBlock();
2119     BasicBlock* thenCase = proc.addBlock();
2120     BasicBlock* elseCase = proc.addBlock();
2121
2122     root->appendNew<ControlValue>(
2123         proc, Branch, Origin(),
2124         root->appendNew<Const32Value>(proc, Origin(), value),
2125         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2126
2127     thenCase->appendNew<ControlValue>(
2128         proc, Return, Origin(),
2129         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2130
2131     elseCase->appendNew<ControlValue>(
2132         proc, Return, Origin(),
2133         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2134
2135     CHECK(compileAndRun<int>(proc) == !!value);
2136 }
2137
2138 void testDiamondFold(int value)
2139 {
2140     Procedure proc;
2141     BasicBlock* root = proc.addBlock();
2142     BasicBlock* thenCase = proc.addBlock();
2143     BasicBlock* elseCase = proc.addBlock();
2144     BasicBlock* done = proc.addBlock();
2145
2146     root->appendNew<ControlValue>(
2147         proc, Branch, Origin(),
2148         root->appendNew<Const32Value>(proc, Origin(), value),
2149         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2150
2151     UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
2152         proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2153     thenCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
2154
2155     UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
2156         proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2157     elseCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done));
2158
2159     Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
2160     thenResult->setPhi(phi);
2161     elseResult->setPhi(phi);
2162     done->appendNew<ControlValue>(proc, Return, Origin(), phi);
2163
2164     CHECK(compileAndRun<int>(proc) == !!value);
2165 }
2166
2167 void testBranchNotEqualFoldPtr(intptr_t value)
2168 {
2169     Procedure proc;
2170     BasicBlock* root = proc.addBlock();
2171     BasicBlock* thenCase = proc.addBlock();
2172     BasicBlock* elseCase = proc.addBlock();
2173
2174     root->appendNew<ControlValue>(
2175         proc, Branch, Origin(),
2176         root->appendNew<Value>(
2177             proc, NotEqual, Origin(),
2178             root->appendNew<ConstPtrValue>(proc, Origin(), value),
2179             root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
2180         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2181
2182     thenCase->appendNew<ControlValue>(
2183         proc, Return, Origin(),
2184         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2185
2186     elseCase->appendNew<ControlValue>(
2187         proc, Return, Origin(),
2188         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2189
2190     CHECK(compileAndRun<int>(proc) == !!value);
2191 }
2192
2193 void testBranchEqualFoldPtr(intptr_t value)
2194 {
2195     Procedure proc;
2196     BasicBlock* root = proc.addBlock();
2197     BasicBlock* thenCase = proc.addBlock();
2198     BasicBlock* elseCase = proc.addBlock();
2199
2200     root->appendNew<ControlValue>(
2201         proc, Branch, Origin(),
2202         root->appendNew<Value>(
2203             proc, Equal, Origin(),
2204             root->appendNew<ConstPtrValue>(proc, Origin(), value),
2205             root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
2206         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2207
2208     thenCase->appendNew<ControlValue>(
2209         proc, Return, Origin(),
2210         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2211
2212     elseCase->appendNew<ControlValue>(
2213         proc, Return, Origin(),
2214         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2215
2216     CHECK(compileAndRun<int>(proc) == !value);
2217 }
2218
2219 void testComplex(unsigned numVars, unsigned numConstructs)
2220 {
2221     double before = monotonicallyIncreasingTimeMS();
2222     
2223     Procedure proc;
2224     BasicBlock* current = proc.addBlock();
2225
2226     Const32Value* one = current->appendNew<Const32Value>(proc, Origin(), 1);
2227
2228     Vector<int32_t> varSlots;
2229     for (unsigned i = numVars; i--;)
2230         varSlots.append(i);
2231
2232     Vector<Value*> vars;
2233     for (int32_t& varSlot : varSlots) {
2234         Value* varSlotPtr = current->appendNew<ConstPtrValue>(proc, Origin(), &varSlot);
2235         vars.append(current->appendNew<MemoryValue>(proc, Load, Int32, Origin(), varSlotPtr));
2236     }
2237
2238     for (unsigned i = 0; i < numConstructs; ++i) {
2239         if (i & 1) {
2240             // Control flow diamond.
2241             unsigned predicateVarIndex = (i >> 1) % numVars;
2242             unsigned thenIncVarIndex = ((i >> 1) + 1) % numVars;
2243             unsigned elseIncVarIndex = ((i >> 1) + 2) % numVars;
2244
2245             BasicBlock* thenBlock = proc.addBlock();
2246             BasicBlock* elseBlock = proc.addBlock();
2247             BasicBlock* continuation = proc.addBlock();
2248
2249             current->appendNew<ControlValue>(
2250                 proc, Branch, Origin(), vars[predicateVarIndex],
2251                 FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
2252
2253             UpsilonValue* thenThenResult = thenBlock->appendNew<UpsilonValue>(
2254                 proc, Origin(),
2255                 thenBlock->appendNew<Value>(proc, Add, Origin(), vars[thenIncVarIndex], one));
2256             UpsilonValue* thenElseResult = thenBlock->appendNew<UpsilonValue>(
2257                 proc, Origin(), vars[elseIncVarIndex]);
2258             thenBlock->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
2259
2260             UpsilonValue* elseElseResult = elseBlock->appendNew<UpsilonValue>(
2261                 proc, Origin(),
2262                 elseBlock->appendNew<Value>(proc, Add, Origin(), vars[elseIncVarIndex], one));
2263             UpsilonValue* elseThenResult = elseBlock->appendNew<UpsilonValue>(
2264                 proc, Origin(), vars[thenIncVarIndex]);
2265             elseBlock->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
2266
2267             Value* thenPhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2268             thenThenResult->setPhi(thenPhi);
2269             elseThenResult->setPhi(thenPhi);
2270             vars[thenIncVarIndex] = thenPhi;
2271             
2272             Value* elsePhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2273             thenElseResult->setPhi(elsePhi);
2274             elseElseResult->setPhi(elsePhi);
2275             vars[elseIncVarIndex] = thenPhi;
2276             
2277             current = continuation;
2278         } else {
2279             // Loop.
2280
2281             BasicBlock* loopEntry = proc.addBlock();
2282             BasicBlock* loopReentry = proc.addBlock();
2283             BasicBlock* loopBody = proc.addBlock();
2284             BasicBlock* loopExit = proc.addBlock();
2285             BasicBlock* loopSkip = proc.addBlock();
2286             BasicBlock* continuation = proc.addBlock();
2287             
2288             Value* startIndex = vars[(i >> 1) % numVars];
2289             Value* startSum = current->appendNew<Const32Value>(proc, Origin(), 0);
2290             current->appendNew<ControlValue>(
2291                 proc, Branch, Origin(), startIndex,
2292                 FrequentedBlock(loopEntry), FrequentedBlock(loopSkip));
2293
2294             UpsilonValue* startIndexForBody = loopEntry->appendNew<UpsilonValue>(
2295                 proc, Origin(), startIndex);
2296             UpsilonValue* startSumForBody = loopEntry->appendNew<UpsilonValue>(
2297                 proc, Origin(), startSum);
2298             loopEntry->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loopBody));
2299
2300             Value* bodyIndex = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
2301             startIndexForBody->setPhi(bodyIndex);
2302             Value* bodySum = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
2303             startSumForBody->setPhi(bodySum);
2304             Value* newBodyIndex = loopBody->appendNew<Value>(proc, Sub, Origin(), bodyIndex, one);
2305             Value* newBodySum = loopBody->appendNew<Value>(
2306                 proc, Add, Origin(),
2307                 bodySum,
2308                 loopBody->appendNew<MemoryValue>(
2309                     proc, Load, Int32, Origin(),
2310                     loopBody->appendNew<Value>(
2311                         proc, Add, Origin(),
2312                         loopBody->appendNew<ConstPtrValue>(proc, Origin(), varSlots.data()),
2313                         loopBody->appendNew<Value>(
2314                             proc, Shl, Origin(),
2315                             loopBody->appendNew<Value>(
2316                                 proc, ZExt32, Origin(),
2317                                 loopBody->appendNew<Value>(
2318                                     proc, BitAnd, Origin(),
2319                                     newBodyIndex,
2320                                     loopBody->appendNew<Const32Value>(
2321                                         proc, Origin(), numVars - 1))),
2322                             loopBody->appendNew<Const32Value>(proc, Origin(), 2)))));
2323             loopBody->appendNew<ControlValue>(
2324                 proc, Branch, Origin(), newBodyIndex,
2325                 FrequentedBlock(loopReentry), FrequentedBlock(loopExit));
2326
2327             loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodyIndex, bodyIndex);
2328             loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodySum, bodySum);
2329             loopReentry->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loopBody));
2330
2331             UpsilonValue* exitSum = loopExit->appendNew<UpsilonValue>(proc, Origin(), newBodySum);
2332             loopExit->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
2333
2334             UpsilonValue* skipSum = loopSkip->appendNew<UpsilonValue>(proc, Origin(), startSum);
2335             loopSkip->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation));
2336
2337             Value* finalSum = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2338             exitSum->setPhi(finalSum);
2339             skipSum->setPhi(finalSum);
2340
2341             current = continuation;
2342             vars[((i >> 1) + 1) % numVars] = finalSum;
2343         }
2344     }
2345
2346     current->appendNew<ControlValue>(proc, Return, Origin(), vars[0]);
2347
2348     compile(proc);
2349
2350     double after = monotonicallyIncreasingTimeMS();
2351     dataLog(toCString("    That took ", after - before, " ms.\n"));
2352 }
2353
2354 void testSimplePatchpoint()
2355 {
2356     Procedure proc;
2357     BasicBlock* root = proc.addBlock();
2358     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2359     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2360     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2361     patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
2362     patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
2363     patchpoint->setGenerator(
2364         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2365             CHECK(params.reps.size() == 3);
2366             CHECK(params.reps[0].isGPR());
2367             CHECK(params.reps[1].isGPR());
2368             CHECK(params.reps[2].isGPR());
2369             jit.move(params.reps[1].gpr(), params.reps[0].gpr());
2370             jit.add32(params.reps[2].gpr(), params.reps[0].gpr());
2371         });
2372     root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
2373
2374     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2375 }
2376
2377 void testSimpleCheck()
2378 {
2379     Procedure proc;
2380     BasicBlock* root = proc.addBlock();
2381     Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2382     CheckValue* check = root->appendNew<CheckValue>(proc, Check, Origin(), arg);
2383     check->setGenerator(
2384         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2385             CHECK(params.reps.size() == 1);
2386             CHECK(params.reps[0].isConstant());
2387             CHECK(params.reps[0].value() == 1);
2388
2389             // This should always work because a function this simple should never have callee
2390             // saves.
2391             jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
2392             jit.emitFunctionEpilogue();
2393             jit.ret();
2394         });
2395     root->appendNew<ControlValue>(
2396         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2397
2398     auto code = compile(proc);
2399     
2400     CHECK(invoke<int>(*code, 0) == 0);
2401     CHECK(invoke<int>(*code, 1) == 42);
2402 }
2403
2404 template<typename LeftFunctor, typename RightFunctor>
2405 void genericTestCompare(
2406     B3::Opcode opcode, const LeftFunctor& leftFunctor, const RightFunctor& rightFunctor,
2407     int left, int right, int result)
2408 {
2409     // Using a compare.
2410     {
2411         Procedure proc;
2412         BasicBlock* root = proc.addBlock();
2413
2414         root->appendNew<ControlValue>(
2415             proc, Return, Origin(),
2416             root->appendNew<Value>(
2417                 proc, NotEqual, Origin(),
2418                 root->appendNew<Value>(
2419                     proc, opcode, Origin(), leftFunctor(root, proc), rightFunctor(root, proc)),
2420                 root->appendNew<Const32Value>(proc, Origin(), 0)));
2421
2422         CHECK(compileAndRun<int>(proc, left, right) == result);
2423     }
2424     
2425     // Using a branch.
2426     {
2427         Procedure proc;
2428         BasicBlock* root = proc.addBlock();
2429         BasicBlock* thenCase = proc.addBlock();
2430         BasicBlock* elseCase = proc.addBlock();
2431
2432         root->appendNew<ControlValue>(
2433             proc, Branch, Origin(),
2434             root->appendNew<Value>(
2435                 proc, opcode, Origin(), leftFunctor(root, proc), rightFunctor(root, proc)),
2436             FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2437
2438         // We use a patchpoint on the then case to ensure that this doesn't get if-converted.
2439         PatchpointValue* patchpoint = thenCase->appendNew<PatchpointValue>(proc, Int32, Origin());
2440         patchpoint->setGenerator(
2441             [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2442                 CHECK(params.reps.size() == 1);
2443                 CHECK(params.reps[0].isGPR());
2444                 jit.move(CCallHelpers::TrustedImm32(1), params.reps[0].gpr());
2445             });
2446         thenCase->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
2447
2448         elseCase->appendNew<ControlValue>(
2449             proc, Return, Origin(),
2450             elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2451
2452         CHECK(compileAndRun<int>(proc, left, right) == result);
2453     }
2454 }
2455
2456 int modelCompare(B3::Opcode opcode, int left, int right)
2457 {
2458     switch (opcode) {
2459     case Equal:
2460         return left == right;
2461     case NotEqual:
2462         return left != right;
2463     case LessThan:
2464         return left < right;
2465     case GreaterThan:
2466         return left > right;
2467     case LessEqual:
2468         return left <= right;
2469     case GreaterEqual:
2470         return left >= right;
2471     case Above:
2472         return static_cast<unsigned>(left) > static_cast<unsigned>(right);
2473     case Below:
2474         return static_cast<unsigned>(left) < static_cast<unsigned>(right);
2475     case AboveEqual:
2476         return static_cast<unsigned>(left) >= static_cast<unsigned>(right);
2477     case BelowEqual:
2478         return static_cast<unsigned>(left) <= static_cast<unsigned>(right);
2479     case BitAnd:
2480         return !!(left & right);
2481     default:
2482         RELEASE_ASSERT_NOT_REACHED();
2483         return 0;
2484     }
2485 }
2486
2487 template<typename T>
2488 void testCompareLoad(B3::Opcode opcode, B3::Opcode loadOpcode, int left, int right)
2489 {
2490     int result = modelCompare(opcode, modelLoad<T>(left), right);
2491     
2492     // Test addr-to-tmp
2493     int slot = left;
2494     genericTestCompare(
2495         opcode,
2496         [&] (BasicBlock* block, Procedure& proc) {
2497             return block->appendNew<MemoryValue>(
2498                 proc, loadOpcode, Int32, Origin(),
2499                 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
2500         },
2501         [&] (BasicBlock* block, Procedure& proc) {
2502             return block->appendNew<Value>(
2503                 proc, Trunc, Origin(),
2504                 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2505         },
2506         left, right, result);
2507
2508     // Test addr-to-imm
2509     slot = left;
2510     genericTestCompare(
2511         opcode,
2512         [&] (BasicBlock* block, Procedure& proc) {
2513             return block->appendNew<MemoryValue>(
2514                 proc, loadOpcode, Int32, Origin(),
2515                 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
2516         },
2517         [&] (BasicBlock* block, Procedure& proc) {
2518             return block->appendNew<Const32Value>(proc, Origin(), right);
2519         },
2520         left, right, result);
2521
2522     result = modelCompare(opcode, left, modelLoad<T>(right));
2523     
2524     // Test tmp-to-addr
2525     slot = right;
2526     genericTestCompare(
2527         opcode,
2528         [&] (BasicBlock* block, Procedure& proc) {
2529             return block->appendNew<Value>(
2530                 proc, Trunc, Origin(),
2531                 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2532         },
2533         [&] (BasicBlock* block, Procedure& proc) {
2534             return block->appendNew<MemoryValue>(
2535                 proc, loadOpcode, Int32, Origin(),
2536                 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
2537         },
2538         left, right, result);
2539
2540     // Test imm-to-addr
2541     slot = right;
2542     genericTestCompare(
2543         opcode,
2544         [&] (BasicBlock* block, Procedure& proc) {
2545             return block->appendNew<Const32Value>(proc, Origin(), left);
2546         },
2547         [&] (BasicBlock* block, Procedure& proc) {
2548             return block->appendNew<MemoryValue>(
2549                 proc, loadOpcode, Int32, Origin(),
2550                 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
2551         },
2552         left, right, result);
2553 }
2554
2555 void testCompareImpl(B3::Opcode opcode, int left, int right)
2556 {
2557     int result = modelCompare(opcode, left, right);
2558     
2559     // Test tmp-to-tmp.
2560     genericTestCompare(
2561         opcode,
2562         [&] (BasicBlock* block, Procedure& proc) {
2563             return block->appendNew<Value>(
2564                 proc, Trunc, Origin(),
2565                 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2566         },
2567         [&] (BasicBlock* block, Procedure& proc) {
2568             return block->appendNew<Value>(
2569                 proc, Trunc, Origin(),
2570                 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2571         },
2572         left, right, result);
2573
2574     // Test imm-to-tmp.
2575     genericTestCompare(
2576         opcode,
2577         [&] (BasicBlock* block, Procedure& proc) {
2578             return block->appendNew<Const32Value>(proc, Origin(), left);
2579         },
2580         [&] (BasicBlock* block, Procedure& proc) {
2581             return block->appendNew<Value>(
2582                 proc, Trunc, Origin(),
2583                 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2584         },
2585         left, right, result);
2586
2587     // Test tmp-to-imm.
2588     genericTestCompare(
2589         opcode,
2590         [&] (BasicBlock* block, Procedure& proc) {
2591             return block->appendNew<Value>(
2592                 proc, Trunc, Origin(),
2593                 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2594         },
2595         [&] (BasicBlock* block, Procedure& proc) {
2596             return block->appendNew<Const32Value>(proc, Origin(), right);
2597         },
2598         left, right, result);
2599
2600     // Test imm-to-imm.
2601     genericTestCompare(
2602         opcode,
2603         [&] (BasicBlock* block, Procedure& proc) {
2604             return block->appendNew<Const32Value>(proc, Origin(), left);
2605         },
2606         [&] (BasicBlock* block, Procedure& proc) {
2607             return block->appendNew<Const32Value>(proc, Origin(), right);
2608         },
2609         left, right, result);
2610
2611     testCompareLoad<int32_t>(opcode, Load, left, right);
2612     testCompareLoad<int8_t>(opcode, Load8S, left, right);
2613     testCompareLoad<uint8_t>(opcode, Load8Z, left, right);
2614     testCompareLoad<int16_t>(opcode, Load16S, left, right);
2615     testCompareLoad<uint16_t>(opcode, Load16Z, left, right);
2616 }
2617
2618 void testCompare(B3::Opcode opcode, int left, int right)
2619 {
2620     auto variants = [&] (int left, int right) {
2621         testCompareImpl(opcode, left, right);
2622         testCompareImpl(opcode, left, right + 1);
2623         testCompareImpl(opcode, left, right - 1);
2624
2625         auto multipliedTests = [&] (int factor) {
2626             testCompareImpl(opcode, left * factor, right);
2627             testCompareImpl(opcode, left * factor, right + 1);
2628             testCompareImpl(opcode, left * factor, right - 1);
2629         
2630             testCompareImpl(opcode, left, right * factor);
2631             testCompareImpl(opcode, left, (right + 1) * factor);
2632             testCompareImpl(opcode, left, (right - 1) * factor);
2633         
2634             testCompareImpl(opcode, left * factor, right * factor);
2635             testCompareImpl(opcode, left * factor, (right + 1) * factor);
2636             testCompareImpl(opcode, left * factor, (right - 1) * factor);
2637         };
2638
2639         multipliedTests(10);
2640         multipliedTests(100);
2641         multipliedTests(1000);
2642         multipliedTests(100000);
2643     };
2644
2645     variants(left, right);
2646     variants(-left, right);
2647     variants(left, -right);
2648     variants(-left, -right);
2649 }
2650
2651 int simpleFunction(int a, int b)
2652 {
2653     return a + b;
2654 }
2655
2656 void testCallSimple(int a, int b)
2657 {
2658     Procedure proc;
2659     BasicBlock* root = proc.addBlock();
2660     root->appendNew<ControlValue>(
2661         proc, Return, Origin(),
2662         root->appendNew<CCallValue>(
2663             proc, Int32, Origin(),
2664             root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunction)),
2665             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2666             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2667
2668     CHECK(compileAndRun<int>(proc, a, b) == a + b);
2669 }
2670
2671 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)
2672 {
2673     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);
2674 }
2675
2676 void testCallFunctionWithHellaArguments()
2677 {
2678     Procedure proc;
2679     BasicBlock* root = proc.addBlock();
2680
2681     Vector<Value*> args;
2682     for (unsigned i = 0; i < 26; ++i)
2683         args.append(root->appendNew<Const32Value>(proc, Origin(), i + 1));
2684
2685     CCallValue* call = root->appendNew<CCallValue>(
2686         proc, Int32, Origin(),
2687         root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(functionWithHellaArguments)));
2688     call->children().appendVector(args);
2689     
2690     root->appendNew<ControlValue>(proc, Return, Origin(), call);
2691
2692     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));
2693 }
2694
2695 void testReturnDouble(double value)
2696 {
2697     Procedure proc;
2698     BasicBlock* root = proc.addBlock();
2699     root->appendNew<ControlValue>(
2700         proc, Return, Origin(),
2701         root->appendNew<ConstDoubleValue>(proc, Origin(), value));
2702
2703     CHECK(isIdentical(compileAndRun<double>(proc), value));
2704 }
2705
2706 double simpleFunctionDouble(double a, double b)
2707 {
2708     return a + b;
2709 }
2710
2711 void testCallSimpleDouble(double a, double b)
2712 {
2713     Procedure proc;
2714     BasicBlock* root = proc.addBlock();
2715     root->appendNew<ControlValue>(
2716         proc, Return, Origin(),
2717         root->appendNew<CCallValue>(
2718             proc, Double, Origin(),
2719             root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunctionDouble)),
2720             root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
2721             root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)));
2722
2723     CHECK(compileAndRun<double>(proc, a, b) == a + b);
2724 }
2725
2726 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)
2727 {
2728     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);
2729 }
2730
2731 void testCallFunctionWithHellaDoubleArguments()
2732 {
2733     Procedure proc;
2734     BasicBlock* root = proc.addBlock();
2735
2736     Vector<Value*> args;
2737     for (unsigned i = 0; i < 26; ++i)
2738         args.append(root->appendNew<ConstDoubleValue>(proc, Origin(), i + 1));
2739
2740     CCallValue* call = root->appendNew<CCallValue>(
2741         proc, Double, Origin(),
2742         root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(functionWithHellaDoubleArguments)));
2743     call->children().appendVector(args);
2744     
2745     root->appendNew<ControlValue>(proc, Return, Origin(), call);
2746
2747     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));
2748 }
2749
2750 #define RUN(test) do {                          \
2751         if (!shouldRun(#test))                  \
2752             break;                              \
2753         tasks.append(                           \
2754             createSharedTask<void()>(           \
2755                 [&] () {                        \
2756                     dataLog(#test "...\n");     \
2757                     test;                       \
2758                     dataLog(#test ": OK!\n");   \
2759                 }));                            \
2760     } while (false);
2761
2762 void run(const char* filter)
2763 {
2764     JSC::initializeThreading();
2765     vm = &VM::create(LargeHeap).leakRef();
2766
2767     Deque<RefPtr<SharedTask<void()>>> tasks;
2768
2769     auto shouldRun = [&] (const char* testName) -> bool {
2770         return !filter || !!strcasestr(testName, filter);
2771     };
2772
2773     RUN(test42());
2774     RUN(testLoad42());
2775     RUN(testArg(43));
2776     RUN(testReturnConst64(5));
2777     RUN(testReturnConst64(-42));
2778
2779     RUN(testAddArgs(1, 1));
2780     RUN(testAddArgs(1, 2));
2781     RUN(testAddArgImm(1, 2));
2782     RUN(testAddArgImm(0, 2));
2783     RUN(testAddArgImm(1, 0));
2784     RUN(testAddImmArg(1, 2));
2785     RUN(testAddImmArg(0, 2));
2786     RUN(testAddImmArg(1, 0));
2787     RUN(testAddArgs32(1, 1));
2788     RUN(testAddArgs32(1, 2));
2789
2790     RUN(testSubArgs(1, 1));
2791     RUN(testSubArgs(1, 2));
2792     RUN(testSubArgs(13, -42));
2793     RUN(testSubArgs(-13, 42));
2794     RUN(testSubArgImm(1, 1));
2795     RUN(testSubArgImm(1, 2));
2796     RUN(testSubArgImm(13, -42));
2797     RUN(testSubArgImm(-13, 42));
2798     RUN(testSubArgImm(42, 0));
2799     RUN(testSubImmArg(1, 1));
2800     RUN(testSubImmArg(1, 2));
2801     RUN(testSubImmArg(13, -42));
2802     RUN(testSubImmArg(-13, 42));
2803
2804     RUN(testSubArgs32(1, 1));
2805     RUN(testSubArgs32(1, 2));
2806     RUN(testSubArgs32(13, -42));
2807     RUN(testSubArgs32(-13, 42));
2808     RUN(testSubArgImm32(1, 1));
2809     RUN(testSubArgImm32(1, 2));
2810     RUN(testSubArgImm32(13, -42));
2811     RUN(testSubArgImm32(-13, 42));
2812     RUN(testSubImmArg32(1, 1));
2813     RUN(testSubImmArg32(1, 2));
2814     RUN(testSubImmArg32(13, -42));
2815     RUN(testSubImmArg32(-13, 42));
2816
2817     RUN(testBitAndArgs(43, 43));
2818     RUN(testBitAndArgs(43, 0));
2819     RUN(testBitAndArgs(10, 3));
2820     RUN(testBitAndArgs(42, 0xffffffffffffffff));
2821     RUN(testBitAndSameArg(43));
2822     RUN(testBitAndSameArg(0));
2823     RUN(testBitAndSameArg(3));
2824     RUN(testBitAndSameArg(0xffffffffffffffff));
2825     RUN(testBitAndImms(43, 43));
2826     RUN(testBitAndImms(43, 0));
2827     RUN(testBitAndImms(10, 3));
2828     RUN(testBitAndImms(42, 0xffffffffffffffff));
2829     RUN(testBitAndArgImm(43, 43));
2830     RUN(testBitAndArgImm(43, 0));
2831     RUN(testBitAndArgImm(10, 3));
2832     RUN(testBitAndArgImm(42, 0xffffffffffffffff));
2833     RUN(testBitAndImmArg(43, 43));
2834     RUN(testBitAndImmArg(43, 0));
2835     RUN(testBitAndImmArg(10, 3));
2836     RUN(testBitAndImmArg(42, 0xffffffffffffffff));
2837     RUN(testBitAndBitAndArgImmImm(2, 7, 3));
2838     RUN(testBitAndBitAndArgImmImm(1, 6, 6));
2839     RUN(testBitAndBitAndArgImmImm(0xffff, 24, 7));
2840     RUN(testBitAndImmBitAndArgImm(7, 2, 3));
2841     RUN(testBitAndImmBitAndArgImm(6, 1, 6));
2842     RUN(testBitAndImmBitAndArgImm(24, 0xffff, 7));
2843     RUN(testBitAndArgs32(43, 43));
2844     RUN(testBitAndArgs32(43, 0));
2845     RUN(testBitAndArgs32(10, 3));
2846     RUN(testBitAndArgs32(42, 0xffffffff));
2847     RUN(testBitAndSameArg32(43));
2848     RUN(testBitAndSameArg32(0));
2849     RUN(testBitAndSameArg32(3));
2850     RUN(testBitAndSameArg32(0xffffffff));
2851     RUN(testBitAndImms32(43, 43));
2852     RUN(testBitAndImms32(43, 0));
2853     RUN(testBitAndImms32(10, 3));
2854     RUN(testBitAndImms32(42, 0xffffffff));
2855     RUN(testBitAndArgImm32(43, 43));
2856     RUN(testBitAndArgImm32(43, 0));
2857     RUN(testBitAndArgImm32(10, 3));
2858     RUN(testBitAndArgImm32(42, 0xffffffff));
2859     RUN(testBitAndImmArg32(43, 43));
2860     RUN(testBitAndImmArg32(43, 0));
2861     RUN(testBitAndImmArg32(10, 3));
2862     RUN(testBitAndImmArg32(42, 0xffffffff));
2863     RUN(testBitAndBitAndArgImmImm32(2, 7, 3));
2864     RUN(testBitAndBitAndArgImmImm32(1, 6, 6));
2865     RUN(testBitAndBitAndArgImmImm32(0xffff, 24, 7));
2866     RUN(testBitAndImmBitAndArgImm32(7, 2, 3));
2867     RUN(testBitAndImmBitAndArgImm32(6, 1, 6));
2868     RUN(testBitAndImmBitAndArgImm32(24, 0xffff, 7));
2869
2870     RUN(testBitOrArgs(43, 43));
2871     RUN(testBitOrArgs(43, 0));
2872     RUN(testBitOrArgs(10, 3));
2873     RUN(testBitOrArgs(42, 0xffffffffffffffff));
2874     RUN(testBitOrSameArg(43));
2875     RUN(testBitOrSameArg(0));
2876     RUN(testBitOrSameArg(3));
2877     RUN(testBitOrSameArg(0xffffffffffffffff));
2878     RUN(testBitOrImms(43, 43));
2879     RUN(testBitOrImms(43, 0));
2880     RUN(testBitOrImms(10, 3));
2881     RUN(testBitOrImms(42, 0xffffffffffffffff));
2882     RUN(testBitOrArgImm(43, 43));
2883     RUN(testBitOrArgImm(43, 0));
2884     RUN(testBitOrArgImm(10, 3));
2885     RUN(testBitOrArgImm(42, 0xffffffffffffffff));
2886     RUN(testBitOrImmArg(43, 43));
2887     RUN(testBitOrImmArg(43, 0));
2888     RUN(testBitOrImmArg(10, 3));
2889     RUN(testBitOrImmArg(42, 0xffffffffffffffff));
2890     RUN(testBitOrBitOrArgImmImm(2, 7, 3));
2891     RUN(testBitOrBitOrArgImmImm(1, 6, 6));
2892     RUN(testBitOrBitOrArgImmImm(0xffff, 24, 7));
2893     RUN(testBitOrImmBitOrArgImm(7, 2, 3));
2894     RUN(testBitOrImmBitOrArgImm(6, 1, 6));
2895     RUN(testBitOrImmBitOrArgImm(24, 0xffff, 7));
2896     RUN(testBitOrArgs32(43, 43));
2897     RUN(testBitOrArgs32(43, 0));
2898     RUN(testBitOrArgs32(10, 3));
2899     RUN(testBitOrArgs32(42, 0xffffffff));
2900     RUN(testBitOrSameArg32(43));
2901     RUN(testBitOrSameArg32(0));
2902     RUN(testBitOrSameArg32(3));
2903     RUN(testBitOrSameArg32(0xffffffff));
2904     RUN(testBitOrImms32(43, 43));
2905     RUN(testBitOrImms32(43, 0));
2906     RUN(testBitOrImms32(10, 3));
2907     RUN(testBitOrImms32(42, 0xffffffff));
2908     RUN(testBitOrArgImm32(43, 43));
2909     RUN(testBitOrArgImm32(43, 0));
2910     RUN(testBitOrArgImm32(10, 3));
2911     RUN(testBitOrArgImm32(42, 0xffffffff));
2912     RUN(testBitOrImmArg32(43, 43));
2913     RUN(testBitOrImmArg32(43, 0));
2914     RUN(testBitOrImmArg32(10, 3));
2915     RUN(testBitOrImmArg32(42, 0xffffffff));
2916     RUN(testBitOrBitOrArgImmImm32(2, 7, 3));
2917     RUN(testBitOrBitOrArgImmImm32(1, 6, 6));
2918     RUN(testBitOrBitOrArgImmImm32(0xffff, 24, 7));
2919     RUN(testBitOrImmBitOrArgImm32(7, 2, 3));
2920     RUN(testBitOrImmBitOrArgImm32(6, 1, 6));
2921     RUN(testBitOrImmBitOrArgImm32(24, 0xffff, 7));
2922
2923     RUN(testBitXorArgs(43, 43));
2924     RUN(testBitXorArgs(43, 0));
2925     RUN(testBitXorArgs(10, 3));
2926     RUN(testBitXorArgs(42, 0xffffffffffffffff));
2927     RUN(testBitXorSameArg(43));
2928     RUN(testBitXorSameArg(0));
2929     RUN(testBitXorSameArg(3));
2930     RUN(testBitXorSameArg(0xffffffffffffffff));
2931     RUN(testBitXorImms(43, 43));
2932     RUN(testBitXorImms(43, 0));
2933     RUN(testBitXorImms(10, 3));
2934     RUN(testBitXorImms(42, 0xffffffffffffffff));
2935     RUN(testBitXorArgImm(43, 43));
2936     RUN(testBitXorArgImm(43, 0));
2937     RUN(testBitXorArgImm(10, 3));
2938     RUN(testBitXorArgImm(42, 0xffffffffffffffff));
2939     RUN(testBitXorImmArg(43, 43));
2940     RUN(testBitXorImmArg(43, 0));
2941     RUN(testBitXorImmArg(10, 3));
2942     RUN(testBitXorImmArg(42, 0xffffffffffffffff));
2943     RUN(testBitXorBitXorArgImmImm(2, 7, 3));
2944     RUN(testBitXorBitXorArgImmImm(1, 6, 6));
2945     RUN(testBitXorBitXorArgImmImm(0xffff, 24, 7));
2946     RUN(testBitXorImmBitXorArgImm(7, 2, 3));
2947     RUN(testBitXorImmBitXorArgImm(6, 1, 6));
2948     RUN(testBitXorImmBitXorArgImm(24, 0xffff, 7));
2949     RUN(testBitXorArgs32(43, 43));
2950     RUN(testBitXorArgs32(43, 0));
2951     RUN(testBitXorArgs32(10, 3));
2952     RUN(testBitXorArgs32(42, 0xffffffff));
2953     RUN(testBitXorSameArg32(43));
2954     RUN(testBitXorSameArg32(0));
2955     RUN(testBitXorSameArg32(3));
2956     RUN(testBitXorSameArg32(0xffffffff));
2957     RUN(testBitXorImms32(43, 43));
2958     RUN(testBitXorImms32(43, 0));
2959     RUN(testBitXorImms32(10, 3));
2960     RUN(testBitXorImms32(42, 0xffffffff));
2961     RUN(testBitXorArgImm32(43, 43));
2962     RUN(testBitXorArgImm32(43, 0));
2963     RUN(testBitXorArgImm32(10, 3));
2964     RUN(testBitXorArgImm32(42, 0xffffffff));
2965     RUN(testBitXorImmArg32(43, 43));
2966     RUN(testBitXorImmArg32(43, 0));
2967     RUN(testBitXorImmArg32(10, 3));
2968     RUN(testBitXorImmArg32(42, 0xffffffff));
2969     RUN(testBitXorBitXorArgImmImm32(2, 7, 3));
2970     RUN(testBitXorBitXorArgImmImm32(1, 6, 6));
2971     RUN(testBitXorBitXorArgImmImm32(0xffff, 24, 7));
2972     RUN(testBitXorImmBitXorArgImm32(7, 2, 3));
2973     RUN(testBitXorImmBitXorArgImm32(6, 1, 6));
2974     RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7));
2975
2976     RUN(testShlArgs(1, 0));
2977     RUN(testShlArgs(1, 1));
2978     RUN(testShlArgs(1, 62));
2979     RUN(testShlArgs(0xffffffffffffffff, 0));
2980     RUN(testShlArgs(0xffffffffffffffff, 1));
2981     RUN(testShlArgs(0xffffffffffffffff, 63));
2982     RUN(testShlImms(1, 0));
2983     RUN(testShlImms(1, 1));
2984     RUN(testShlImms(1, 62));
2985     RUN(testShlImms(1, 65));
2986     RUN(testShlImms(0xffffffffffffffff, 0));
2987     RUN(testShlImms(0xffffffffffffffff, 1));
2988     RUN(testShlImms(0xffffffffffffffff, 63));
2989     RUN(testShlArgImm(1, 0));
2990     RUN(testShlArgImm(1, 1));
2991     RUN(testShlArgImm(1, 62));
2992     RUN(testShlArgImm(1, 65));
2993     RUN(testShlArgImm(0xffffffffffffffff, 0));
2994     RUN(testShlArgImm(0xffffffffffffffff, 1));
2995     RUN(testShlArgImm(0xffffffffffffffff, 63));
2996     RUN(testShlArgs32(1, 0));
2997     RUN(testShlArgs32(1, 1));
2998     RUN(testShlArgs32(1, 62));
2999     RUN(testShlImms32(1, 33));
3000     RUN(testShlArgs32(0xffffffff, 0));
3001     RUN(testShlArgs32(0xffffffff, 1));
3002     RUN(testShlArgs32(0xffffffff, 63));
3003     RUN(testShlImms32(1, 0));
3004     RUN(testShlImms32(1, 1));
3005     RUN(testShlImms32(1, 62));
3006     RUN(testShlImms32(1, 33));
3007     RUN(testShlImms32(0xffffffff, 0));
3008     RUN(testShlImms32(0xffffffff, 1));
3009     RUN(testShlImms32(0xffffffff, 63));
3010     RUN(testShlArgImm32(1, 0));
3011     RUN(testShlArgImm32(1, 1));
3012     RUN(testShlArgImm32(1, 62));
3013     RUN(testShlArgImm32(0xffffffff, 0));
3014     RUN(testShlArgImm32(0xffffffff, 1));
3015     RUN(testShlArgImm32(0xffffffff, 63));
3016
3017     RUN(testSShrArgs(1, 0));
3018     RUN(testSShrArgs(1, 1));
3019     RUN(testSShrArgs(1, 62));
3020     RUN(testSShrArgs(0xffffffffffffffff, 0));
3021     RUN(testSShrArgs(0xffffffffffffffff, 1));
3022     RUN(testSShrArgs(0xffffffffffffffff, 63));
3023     RUN(testSShrImms(1, 0));
3024     RUN(testSShrImms(1, 1));
3025     RUN(testSShrImms(1, 62));
3026     RUN(testSShrImms(1, 65));
3027     RUN(testSShrImms(0xffffffffffffffff, 0));
3028     RUN(testSShrImms(0xffffffffffffffff, 1));
3029     RUN(testSShrImms(0xffffffffffffffff, 63));
3030     RUN(testSShrArgImm(1, 0));
3031     RUN(testSShrArgImm(1, 1));
3032     RUN(testSShrArgImm(1, 62));
3033     RUN(testSShrArgImm(1, 65));
3034     RUN(testSShrArgImm(0xffffffffffffffff, 0));
3035     RUN(testSShrArgImm(0xffffffffffffffff, 1));
3036     RUN(testSShrArgImm(0xffffffffffffffff, 63));
3037     RUN(testSShrArgs32(1, 0));
3038     RUN(testSShrArgs32(1, 1));
3039     RUN(testSShrArgs32(1, 62));
3040     RUN(testSShrArgs32(1, 33));
3041     RUN(testSShrArgs32(0xffffffff, 0));
3042     RUN(testSShrArgs32(0xffffffff, 1));
3043     RUN(testSShrArgs32(0xffffffff, 63));
3044     RUN(testSShrImms32(1, 0));
3045     RUN(testSShrImms32(1, 1));
3046     RUN(testSShrImms32(1, 62));
3047     RUN(testSShrImms32(1, 33));
3048     RUN(testSShrImms32(0xffffffff, 0));
3049     RUN(testSShrImms32(0xffffffff, 1));
3050     RUN(testSShrImms32(0xffffffff, 63));
3051     RUN(testSShrArgImm32(1, 0));
3052     RUN(testSShrArgImm32(1, 1));
3053     RUN(testSShrArgImm32(1, 62));
3054     RUN(testSShrArgImm32(0xffffffff, 0));
3055     RUN(testSShrArgImm32(0xffffffff, 1));
3056     RUN(testSShrArgImm32(0xffffffff, 63));
3057
3058     RUN(testZShrArgs(1, 0));
3059     RUN(testZShrArgs(1, 1));
3060     RUN(testZShrArgs(1, 62));
3061     RUN(testZShrArgs(0xffffffffffffffff, 0));
3062     RUN(testZShrArgs(0xffffffffffffffff, 1));
3063     RUN(testZShrArgs(0xffffffffffffffff, 63));
3064     RUN(testZShrImms(1, 0));
3065     RUN(testZShrImms(1, 1));
3066     RUN(testZShrImms(1, 62));
3067     RUN(testZShrImms(1, 65));
3068     RUN(testZShrImms(0xffffffffffffffff, 0));
3069     RUN(testZShrImms(0xffffffffffffffff, 1));
3070     RUN(testZShrImms(0xffffffffffffffff, 63));
3071     RUN(testZShrArgImm(1, 0));
3072     RUN(testZShrArgImm(1, 1));
3073     RUN(testZShrArgImm(1, 62));
3074     RUN(testZShrArgImm(1, 65));
3075     RUN(testZShrArgImm(0xffffffffffffffff, 0));
3076     RUN(testZShrArgImm(0xffffffffffffffff, 1));
3077     RUN(testZShrArgImm(0xffffffffffffffff, 63));
3078     RUN(testZShrArgs32(1, 0));
3079     RUN(testZShrArgs32(1, 1));
3080     RUN(testZShrArgs32(1, 62));
3081     RUN(testZShrArgs32(1, 33));
3082     RUN(testZShrArgs32(0xffffffff, 0));
3083     RUN(testZShrArgs32(0xffffffff, 1));
3084     RUN(testZShrArgs32(0xffffffff, 63));
3085     RUN(testZShrImms32(1, 0));
3086     RUN(testZShrImms32(1, 1));
3087     RUN(testZShrImms32(1, 62));
3088     RUN(testZShrImms32(1, 33));
3089     RUN(testZShrImms32(0xffffffff, 0));
3090     RUN(testZShrImms32(0xffffffff, 1));
3091     RUN(testZShrImms32(0xffffffff, 63));
3092     RUN(testZShrArgImm32(1, 0));
3093     RUN(testZShrArgImm32(1, 1));
3094     RUN(testZShrArgImm32(1, 62));
3095     RUN(testZShrArgImm32(0xffffffff, 0));
3096     RUN(testZShrArgImm32(0xffffffff, 1));
3097     RUN(testZShrArgImm32(0xffffffff, 63));
3098
3099     RUN(testStore(44));
3100     RUN(testStoreConstant(49));
3101     RUN(testStoreConstantPtr(49));
3102     RUN(testTrunc((static_cast<int64_t>(1) << 40) + 42));
3103     RUN(testAdd1(45));
3104     RUN(testAdd1Ptr(51));
3105     RUN(testAdd1Ptr(bitwise_cast<intptr_t>(vm)));
3106     RUN(testNeg32(52));
3107     RUN(testNegPtr(53));
3108     RUN(testStoreAddLoad(46));
3109     RUN(testStoreSubLoad(46));
3110     RUN(testStoreAddLoadInterference(52));
3111     RUN(testStoreAddAndLoad(47, 0xffff));
3112     RUN(testStoreAddAndLoad(470000, 0xffff));
3113     RUN(testStoreNegLoad32(54));
3114     RUN(testStoreNegLoadPtr(55));
3115     RUN(testAdd1Uncommuted(48));
3116     RUN(testLoadOffset());
3117     RUN(testLoadOffsetNotConstant());
3118     RUN(testLoadOffsetUsingAdd());
3119     RUN(testLoadOffsetUsingAddInterference());
3120     RUN(testLoadOffsetUsingAddNotConstant());
3121     RUN(testFramePointer());
3122     RUN(testStackSlot());
3123     RUN(testLoadFromFramePointer());
3124     RUN(testStoreLoadStackSlot(50));
3125     
3126     RUN(testBranch());
3127     RUN(testBranchPtr());
3128     RUN(testDiamond());
3129     RUN(testBranchNotEqual());
3130     RUN(testBranchNotEqualCommute());
3131     RUN(testBranchNotEqualNotEqual());
3132     RUN(testBranchEqual());
3133     RUN(testBranchEqualEqual());
3134     RUN(testBranchEqualCommute());
3135     RUN(testBranchEqualEqual1());
3136     RUN(testBranchFold(42));
3137     RUN(testBranchFold(0));
3138     RUN(testDiamondFold(42));
3139     RUN(testDiamondFold(0));
3140     RUN(testBranchNotEqualFoldPtr(42));
3141     RUN(testBranchNotEqualFoldPtr(0));
3142     RUN(testBranchEqualFoldPtr(42));
3143     RUN(testBranchEqualFoldPtr(0));
3144
3145     RUN(testComplex(64, 128));
3146     RUN(testComplex(64, 256));
3147     RUN(testComplex(64, 384));
3148     RUN(testComplex(4, 128));
3149     RUN(testComplex(4, 256));
3150     RUN(testComplex(4, 384));
3151
3152     RUN(testSimplePatchpoint());
3153     RUN(testSimpleCheck());
3154
3155     RUN(testCompare(Equal, 42, 42));
3156     RUN(testCompare(NotEqual, 42, 42));
3157     RUN(testCompare(LessThan, 42, 42));
3158     RUN(testCompare(GreaterThan, 42, 42));
3159     RUN(testCompare(LessEqual, 42, 42));
3160     RUN(testCompare(GreaterEqual, 42, 42));
3161     RUN(testCompare(Below, 42, 42));
3162     RUN(testCompare(Above, 42, 42));
3163     RUN(testCompare(BelowEqual, 42, 42));
3164     RUN(testCompare(AboveEqual, 42, 42));
3165
3166     RUN(testCompare(BitAnd, 42, 42));
3167     RUN(testCompare(BitAnd, 42, 0));
3168
3169     RUN(testLoad<int32_t>(Load, 60));
3170     RUN(testLoad<int32_t>(Load, -60));
3171     RUN(testLoad<int32_t>(Load, 1000));
3172     RUN(testLoad<int32_t>(Load, -1000));
3173     RUN(testLoad<int32_t>(Load, 1000000));
3174     RUN(testLoad<int32_t>(Load, -1000000));
3175     RUN(testLoad<int32_t>(Load, 1000000000));
3176     RUN(testLoad<int32_t>(Load, -1000000000));
3177     
3178     RUN(testLoad<int8_t>(Load8S, 60));
3179     RUN(testLoad<int8_t>(Load8S, -60));
3180     RUN(testLoad<int8_t>(Load8S, 1000));
3181     RUN(testLoad<int8_t>(Load8S, -1000));
3182     RUN(testLoad<int8_t>(Load8S, 1000000));
3183     RUN(testLoad<int8_t>(Load8S, -1000000));
3184     RUN(testLoad<int8_t>(Load8S, 1000000000));
3185     RUN(testLoad<int8_t>(Load8S, -1000000000));
3186     
3187     RUN(testLoad<uint8_t>(Load8Z, 60));
3188     RUN(testLoad<uint8_t>(Load8Z, -60));
3189     RUN(testLoad<uint8_t>(Load8Z, 1000));
3190     RUN(testLoad<uint8_t>(Load8Z, -1000));
3191     RUN(testLoad<uint8_t>(Load8Z, 1000000));
3192     RUN(testLoad<uint8_t>(Load8Z, -1000000));
3193     RUN(testLoad<uint8_t>(Load8Z, 1000000000));
3194     RUN(testLoad<uint8_t>(Load8Z, -1000000000));
3195
3196     RUN(testLoad<int16_t>(Load16S, 60));
3197     RUN(testLoad<int16_t>(Load16S, -60));
3198     RUN(testLoad<int16_t>(Load16S, 1000));
3199     RUN(testLoad<int16_t>(Load16S, -1000));
3200     RUN(testLoad<int16_t>(Load16S, 1000000));
3201     RUN(testLoad<int16_t>(Load16S, -1000000));
3202     RUN(testLoad<int16_t>(Load16S, 1000000000));
3203     RUN(testLoad<int16_t>(Load16S, -1000000000));
3204     
3205     RUN(testLoad<uint16_t>(Load16Z, 60));
3206     RUN(testLoad<uint16_t>(Load16Z, -60));
3207     RUN(testLoad<uint16_t>(Load16Z, 1000));
3208     RUN(testLoad<uint16_t>(Load16Z, -1000));
3209     RUN(testLoad<uint16_t>(Load16Z, 1000000));
3210     RUN(testLoad<uint16_t>(Load16Z, -1000000));
3211     RUN(testLoad<uint16_t>(Load16Z, 1000000000));
3212     RUN(testLoad<uint16_t>(Load16Z, -1000000000));
3213
3214     RUN(testCallSimple(1, 2));
3215     RUN(testCallFunctionWithHellaArguments());
3216
3217     RUN(testReturnDouble(0.0));
3218     RUN(testReturnDouble(-0.0));
3219     RUN(testReturnDouble(42.5));
3220
3221     RUN(testCallSimpleDouble(1, 2));
3222     RUN(testCallFunctionWithHellaDoubleArguments());
3223
3224     if (tasks.isEmpty())
3225         usage();
3226
3227     Lock lock;
3228
3229     Vector<ThreadIdentifier> threads;
3230     for (unsigned i = filter ? 1 : WTF::numberOfProcessorCores(); i--;) {
3231         threads.append(
3232             createThread(
3233                 "testb3 thread",
3234                 [&] () {
3235                     for (;;) {
3236                         RefPtr<SharedTask<void()>> task;
3237                         {
3238                             LockHolder locker(lock);
3239                             if (tasks.isEmpty())
3240                                 return;
3241                             task = tasks.takeFirst();
3242                         }
3243
3244                         task->run();
3245                     }
3246                 }));
3247     }
3248
3249     for (ThreadIdentifier thread : threads)
3250         waitForThreadCompletion(thread);
3251 }
3252
3253 } // anonymous namespace
3254
3255 #else // ENABLE(B3_JIT)
3256
3257 static void run(const char*)
3258 {
3259     dataLog("B3 JIT is not enabled.\n");
3260 }
3261
3262 #endif // ENABLE(B3_JIT)
3263
3264 int main(int argc, char** argv)
3265 {
3266     const char* filter = nullptr;
3267     switch (argc) {
3268     case 1:
3269         break;
3270     case 2:
3271         filter = argv[1];
3272         break;
3273     default:
3274         usage();
3275         break;
3276     }
3277     
3278     run(filter);
3279     return 0;
3280 }
3281