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