Split testb3 into multiple files
[WebKit-https.git] / Source / JavaScriptCore / b3 / testb3_4.cpp
1 /*
2  * Copyright (C) 2015-2019 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 #include "testb3.h"
28
29 #if ENABLE(B3_JIT)
30
31 void testStoreRelAddLoadAcq32(int amount)
32 {
33     Procedure proc;
34     BasicBlock* root = proc.addBlock();
35     int slot = 37;
36     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
37     root->appendNew<MemoryValue>(
38         proc, Store, Origin(),
39         root->appendNew<Value>(
40             proc, Add, Origin(),
41             root->appendNew<MemoryValue>(
42                 proc, Load, Int32, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
43             root->appendNew<Value>(
44                 proc, Trunc, Origin(),
45                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
46         slotPtr, 0, HeapRange(42), HeapRange(42));
47     root->appendNewControlValue(
48         proc, Return, Origin(),
49         root->appendNew<Const32Value>(proc, Origin(), 0));
50
51     auto code = compileProc(proc);
52     if (isARM64()) {
53         checkUsesInstruction(*code, "lda");
54         checkUsesInstruction(*code, "stl");
55     }
56     if (isX86())
57         checkUsesInstruction(*code, "xchg");
58     CHECK(!invoke<int>(*code, amount));
59     CHECK(slot == 37 + amount);
60 }
61
62 void testStoreAddLoadImm32(int amount)
63 {
64     Procedure proc;
65     BasicBlock* root = proc.addBlock();
66     int slot = 37;
67     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
68     root->appendNew<MemoryValue>(
69         proc, Store, Origin(),
70         root->appendNew<Value>(
71             proc, Add, Origin(),
72             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
73             root->appendNew<Const32Value>(proc, Origin(), amount)),
74         slotPtr, 0);
75     root->appendNewControlValue(
76         proc, Return, Origin(),
77         root->appendNew<Const32Value>(proc, Origin(), 0));
78
79     CHECK(!compileAndRun<int>(proc));
80     CHECK(slot == 37 + amount);
81 }
82
83 void testStoreAddLoad8(int amount, B3::Opcode loadOpcode)
84 {
85     Procedure proc;
86     BasicBlock* root = proc.addBlock();
87     int8_t slot = 37;
88     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
89     root->appendNew<MemoryValue>(
90         proc, Store8, Origin(),
91         root->appendNew<Value>(
92             proc, Add, Origin(),
93             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
94             root->appendNew<Value>(
95                 proc, Trunc, Origin(),
96                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
97         slotPtr, 0);
98     root->appendNewControlValue(
99         proc, Return, Origin(),
100         root->appendNew<Const32Value>(proc, Origin(), 0));
101
102     CHECK(!compileAndRun<int>(proc, amount));
103     CHECK(slot == 37 + amount);
104 }
105
106 void testStoreRelAddLoadAcq8(int amount, B3::Opcode loadOpcode)
107 {
108     Procedure proc;
109     BasicBlock* root = proc.addBlock();
110     int8_t slot = 37;
111     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
112     root->appendNew<MemoryValue>(
113         proc, Store8, Origin(),
114         root->appendNew<Value>(
115             proc, Add, Origin(),
116             root->appendNew<MemoryValue>(
117                 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
118             root->appendNew<Value>(
119                 proc, Trunc, Origin(),
120                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
121         slotPtr, 0, HeapRange(42), HeapRange(42));
122     root->appendNewControlValue(
123         proc, Return, Origin(),
124         root->appendNew<Const32Value>(proc, Origin(), 0));
125
126     auto code = compileProc(proc);
127     if (isARM64()) {
128         checkUsesInstruction(*code, "lda");
129         checkUsesInstruction(*code, "stl");
130     }
131     if (isX86())
132         checkUsesInstruction(*code, "xchg");
133     CHECK(!invoke<int>(*code, amount));
134     CHECK(slot == 37 + amount);
135 }
136
137 void testStoreRelAddFenceLoadAcq8(int amount, B3::Opcode loadOpcode)
138 {
139     Procedure proc;
140     BasicBlock* root = proc.addBlock();
141     int8_t slot = 37;
142     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
143     Value* loadedValue = root->appendNew<MemoryValue>(
144         proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42));
145     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
146     patchpoint->clobber(RegisterSet::macroScratchRegisters());
147     patchpoint->setGenerator(
148         [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
149             AllowMacroScratchRegisterUsage allowScratch(jit);
150             jit.store8(CCallHelpers::TrustedImm32(0xbeef), &slot);
151         });
152     patchpoint->effects = Effects::none();
153     patchpoint->effects.fence = true;
154     root->appendNew<MemoryValue>(
155         proc, Store8, Origin(),
156         root->appendNew<Value>(
157             proc, Add, Origin(),
158             loadedValue,
159             root->appendNew<Value>(
160                 proc, Trunc, Origin(),
161                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
162         slotPtr, 0, HeapRange(42), HeapRange(42));
163     root->appendNewControlValue(
164         proc, Return, Origin(),
165         root->appendNew<Const32Value>(proc, Origin(), 0));
166
167     auto code = compileProc(proc);
168     if (isARM64()) {
169         checkUsesInstruction(*code, "lda");
170         checkUsesInstruction(*code, "stl");
171     }
172     if (isX86())
173         checkUsesInstruction(*code, "xchg");
174     CHECK(!invoke<int>(*code, amount));
175     CHECK(slot == 37 + amount);
176 }
177
178 void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode)
179 {
180     Procedure proc;
181     BasicBlock* root = proc.addBlock();
182     int8_t slot = 37;
183     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
184     root->appendNew<MemoryValue>(
185         proc, Store8, Origin(),
186         root->appendNew<Value>(
187             proc, Add, Origin(),
188             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
189             root->appendNew<Const32Value>(proc, Origin(), amount)),
190         slotPtr, 0);
191     root->appendNewControlValue(
192         proc, Return, Origin(),
193         root->appendNew<Const32Value>(proc, Origin(), 0));
194
195     CHECK(!compileAndRun<int>(proc));
196     CHECK(slot == 37 + amount);
197 }
198
199 void testStoreAddLoad16(int amount, B3::Opcode loadOpcode)
200 {
201     Procedure proc;
202     BasicBlock* root = proc.addBlock();
203     int16_t slot = 37;
204     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
205     root->appendNew<MemoryValue>(
206         proc, Store16, Origin(),
207         root->appendNew<Value>(
208             proc, Add, Origin(),
209             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
210             root->appendNew<Value>(
211                 proc, Trunc, Origin(),
212                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
213         slotPtr, 0);
214     root->appendNewControlValue(
215         proc, Return, Origin(),
216         root->appendNew<Const32Value>(proc, Origin(), 0));
217
218     CHECK(!compileAndRun<int>(proc, amount));
219     CHECK(slot == 37 + amount);
220 }
221
222 void testStoreRelAddLoadAcq16(int amount, B3::Opcode loadOpcode)
223 {
224     Procedure proc;
225     BasicBlock* root = proc.addBlock();
226     int16_t slot = 37;
227     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
228     root->appendNew<MemoryValue>(
229         proc, Store16, Origin(),
230         root->appendNew<Value>(
231             proc, Add, Origin(),
232             root->appendNew<MemoryValue>(
233                 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
234             root->appendNew<Value>(
235                 proc, Trunc, Origin(),
236                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
237         slotPtr, 0, HeapRange(42), HeapRange(42));
238     root->appendNewControlValue(
239         proc, Return, Origin(),
240         root->appendNew<Const32Value>(proc, Origin(), 0));
241
242     auto code = compileProc(proc);
243     if (isARM64()) {
244         checkUsesInstruction(*code, "lda");
245         checkUsesInstruction(*code, "stl");
246     }
247     if (isX86())
248         checkUsesInstruction(*code, "xchg");
249     CHECK(!invoke<int>(*code, amount));
250     CHECK(slot == 37 + amount);
251 }
252
253 void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode)
254 {
255     Procedure proc;
256     BasicBlock* root = proc.addBlock();
257     int16_t slot = 37;
258     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
259     root->appendNew<MemoryValue>(
260         proc, Store16, Origin(),
261         root->appendNew<Value>(
262             proc, Add, Origin(),
263             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
264             root->appendNew<Const32Value>(proc, Origin(), amount)),
265         slotPtr, 0);
266     root->appendNewControlValue(
267         proc, Return, Origin(),
268         root->appendNew<Const32Value>(proc, Origin(), 0));
269
270     CHECK(!compileAndRun<int>(proc));
271     CHECK(slot == 37 + amount);
272 }
273
274 void testStoreAddLoad64(int amount)
275 {
276     Procedure proc;
277     BasicBlock* root = proc.addBlock();
278     int64_t slot = 37000000000ll;
279     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
280     root->appendNew<MemoryValue>(
281         proc, Store, Origin(),
282         root->appendNew<Value>(
283             proc, Add, Origin(),
284             root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
285             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
286         slotPtr, 0);
287     root->appendNewControlValue(
288         proc, Return, Origin(),
289         root->appendNew<Const32Value>(proc, Origin(), 0));
290
291     CHECK(!compileAndRun<int>(proc, amount));
292     CHECK(slot == 37000000000ll + amount);
293 }
294
295 void testStoreRelAddLoadAcq64(int amount)
296 {
297     Procedure proc;
298     BasicBlock* root = proc.addBlock();
299     int64_t slot = 37000000000ll;
300     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
301     root->appendNew<MemoryValue>(
302         proc, Store, Origin(),
303         root->appendNew<Value>(
304             proc, Add, Origin(),
305             root->appendNew<MemoryValue>(
306                 proc, Load, Int64, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
307             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
308         slotPtr, 0, HeapRange(42), HeapRange(42));
309     root->appendNewControlValue(
310         proc, Return, Origin(),
311         root->appendNew<Const32Value>(proc, Origin(), 0));
312
313     auto code = compileProc(proc);
314     if (isARM64()) {
315         checkUsesInstruction(*code, "lda");
316         checkUsesInstruction(*code, "stl");
317     }
318     if (isX86())
319         checkUsesInstruction(*code, "xchg");
320     CHECK(!invoke<int>(*code, amount));
321     CHECK(slot == 37000000000ll + amount);
322 }
323
324 void testStoreAddLoadImm64(int64_t amount)
325 {
326     Procedure proc;
327     BasicBlock* root = proc.addBlock();
328     int64_t slot = 370000000000ll;
329     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
330     root->appendNew<MemoryValue>(
331         proc, Store, Origin(),
332         root->appendNew<Value>(
333             proc, Add, Origin(),
334             root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
335             root->appendNew<Const64Value>(proc, Origin(), amount)),
336         slotPtr, 0);
337     root->appendNewControlValue(
338         proc, Return, Origin(),
339         root->appendNew<Const32Value>(proc, Origin(), 0));
340
341     CHECK(!compileAndRun<int>(proc));
342     CHECK(slot == 370000000000ll + amount);
343 }
344
345 void testStoreAddLoad32Index(int amount)
346 {
347     Procedure proc;
348     BasicBlock* root = proc.addBlock();
349     int slot = 37;
350     int* ptr = &slot;
351     intptr_t zero = 0;
352     Value* slotPtr = root->appendNew<Value>(
353         proc, Add, Origin(),
354         root->appendNew<MemoryValue>(
355             proc, Load, pointerType(), Origin(),
356             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
357         root->appendNew<MemoryValue>(
358             proc, Load, pointerType(), Origin(),
359             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
360     root->appendNew<MemoryValue>(
361         proc, Store, Origin(),
362         root->appendNew<Value>(
363             proc, Add, Origin(),
364             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
365             root->appendNew<Value>(
366                 proc, Trunc, Origin(),
367                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
368         slotPtr, 0);
369     root->appendNewControlValue(
370         proc, Return, Origin(),
371         root->appendNew<Const32Value>(proc, Origin(), 0));
372
373     CHECK(!compileAndRun<int>(proc, amount));
374     CHECK(slot == 37 + amount);
375 }
376
377 void testStoreAddLoadImm32Index(int amount)
378 {
379     Procedure proc;
380     BasicBlock* root = proc.addBlock();
381     int slot = 37;
382     int* ptr = &slot;
383     intptr_t zero = 0;
384     Value* slotPtr = root->appendNew<Value>(
385         proc, Add, Origin(),
386         root->appendNew<MemoryValue>(
387             proc, Load, pointerType(), Origin(),
388             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
389         root->appendNew<MemoryValue>(
390             proc, Load, pointerType(), Origin(),
391             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
392     root->appendNew<MemoryValue>(
393         proc, Store, Origin(),
394         root->appendNew<Value>(
395             proc, Add, Origin(),
396             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
397             root->appendNew<Const32Value>(proc, Origin(), amount)),
398         slotPtr, 0);
399     root->appendNewControlValue(
400         proc, Return, Origin(),
401         root->appendNew<Const32Value>(proc, Origin(), 0));
402
403     CHECK(!compileAndRun<int>(proc));
404     CHECK(slot == 37 + amount);
405 }
406
407 void testStoreAddLoad8Index(int amount, B3::Opcode loadOpcode)
408 {
409     Procedure proc;
410     BasicBlock* root = proc.addBlock();
411     int8_t slot = 37;
412     int8_t* ptr = &slot;
413     intptr_t zero = 0;
414     Value* slotPtr = root->appendNew<Value>(
415         proc, Add, Origin(),
416         root->appendNew<MemoryValue>(
417             proc, Load, pointerType(), Origin(),
418             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
419         root->appendNew<MemoryValue>(
420             proc, Load, pointerType(), Origin(),
421             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
422     root->appendNew<MemoryValue>(
423         proc, Store8, Origin(),
424         root->appendNew<Value>(
425             proc, Add, Origin(),
426             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
427             root->appendNew<Value>(
428                 proc, Trunc, Origin(),
429                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
430         slotPtr);
431     root->appendNewControlValue(
432         proc, Return, Origin(),
433         root->appendNew<Const32Value>(proc, Origin(), 0));
434
435     CHECK(!compileAndRun<int>(proc, amount));
436     CHECK(slot == 37 + amount);
437 }
438
439 void testStoreAddLoadImm8Index(int amount, B3::Opcode loadOpcode)
440 {
441     Procedure proc;
442     BasicBlock* root = proc.addBlock();
443     int8_t slot = 37;
444     int8_t* ptr = &slot;
445     intptr_t zero = 0;
446     Value* slotPtr = root->appendNew<Value>(
447         proc, Add, Origin(),
448         root->appendNew<MemoryValue>(
449             proc, Load, pointerType(), Origin(),
450             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
451         root->appendNew<MemoryValue>(
452             proc, Load, pointerType(), Origin(),
453             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
454     root->appendNew<MemoryValue>(
455         proc, Store8, Origin(),
456         root->appendNew<Value>(
457             proc, Add, Origin(),
458             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
459             root->appendNew<Const32Value>(proc, Origin(), amount)),
460         slotPtr);
461     root->appendNewControlValue(
462         proc, Return, Origin(),
463         root->appendNew<Const32Value>(proc, Origin(), 0));
464
465     CHECK(!compileAndRun<int>(proc));
466     CHECK(slot == 37 + amount);
467 }
468
469 void testStoreAddLoad16Index(int amount, B3::Opcode loadOpcode)
470 {
471     Procedure proc;
472     BasicBlock* root = proc.addBlock();
473     int16_t slot = 37;
474     int16_t* ptr = &slot;
475     intptr_t zero = 0;
476     Value* slotPtr = root->appendNew<Value>(
477         proc, Add, Origin(),
478         root->appendNew<MemoryValue>(
479             proc, Load, pointerType(), Origin(),
480             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
481         root->appendNew<MemoryValue>(
482             proc, Load, pointerType(), Origin(),
483             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
484     root->appendNew<MemoryValue>(
485         proc, Store16, Origin(),
486         root->appendNew<Value>(
487             proc, Add, Origin(),
488             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
489             root->appendNew<Value>(
490                 proc, Trunc, Origin(),
491                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
492         slotPtr);
493     root->appendNewControlValue(
494         proc, Return, Origin(),
495         root->appendNew<Const32Value>(proc, Origin(), 0));
496
497     CHECK(!compileAndRun<int>(proc, amount));
498     CHECK(slot == 37 + amount);
499 }
500
501 void testStoreAddLoadImm16Index(int amount, B3::Opcode loadOpcode)
502 {
503     Procedure proc;
504     BasicBlock* root = proc.addBlock();
505     int16_t slot = 37;
506     int16_t* ptr = &slot;
507     intptr_t zero = 0;
508     Value* slotPtr = root->appendNew<Value>(
509         proc, Add, Origin(),
510         root->appendNew<MemoryValue>(
511             proc, Load, pointerType(), Origin(),
512             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
513         root->appendNew<MemoryValue>(
514             proc, Load, pointerType(), Origin(),
515             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
516     root->appendNew<MemoryValue>(
517         proc, Store16, Origin(),
518         root->appendNew<Value>(
519             proc, Add, Origin(),
520             root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
521             root->appendNew<Const32Value>(proc, Origin(), amount)),
522         slotPtr);
523     root->appendNewControlValue(
524         proc, Return, Origin(),
525         root->appendNew<Const32Value>(proc, Origin(), 0));
526
527     CHECK(!compileAndRun<int>(proc));
528     CHECK(slot == 37 + amount);
529 }
530
531 void testStoreAddLoad64Index(int amount)
532 {
533     Procedure proc;
534     BasicBlock* root = proc.addBlock();
535     int64_t slot = 37000000000ll;
536     int64_t* ptr = &slot;
537     intptr_t zero = 0;
538     Value* slotPtr = root->appendNew<Value>(
539         proc, Add, Origin(),
540         root->appendNew<MemoryValue>(
541             proc, Load, pointerType(), Origin(),
542             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
543         root->appendNew<MemoryValue>(
544             proc, Load, pointerType(), Origin(),
545             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
546     root->appendNew<MemoryValue>(
547         proc, Store, Origin(),
548         root->appendNew<Value>(
549             proc, Add, Origin(),
550             root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
551             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
552         slotPtr, 0);
553     root->appendNewControlValue(
554         proc, Return, Origin(),
555         root->appendNew<Const32Value>(proc, Origin(), 0));
556
557     CHECK(!compileAndRun<int>(proc, amount));
558     CHECK(slot == 37000000000ll + amount);
559 }
560
561 void testStoreAddLoadImm64Index(int64_t amount)
562 {
563     Procedure proc;
564     BasicBlock* root = proc.addBlock();
565     int64_t slot = 370000000000ll;
566     int64_t* ptr = &slot;
567     intptr_t zero = 0;
568     Value* slotPtr = root->appendNew<Value>(
569         proc, Add, Origin(),
570         root->appendNew<MemoryValue>(
571             proc, Load, pointerType(), Origin(),
572             root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
573         root->appendNew<MemoryValue>(
574             proc, Load, pointerType(), Origin(),
575             root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
576     root->appendNew<MemoryValue>(
577         proc, Store, Origin(),
578         root->appendNew<Value>(
579             proc, Add, Origin(),
580             root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
581             root->appendNew<Const64Value>(proc, Origin(), amount)),
582         slotPtr, 0);
583     root->appendNewControlValue(
584         proc, Return, Origin(),
585         root->appendNew<Const32Value>(proc, Origin(), 0));
586
587     CHECK(!compileAndRun<int>(proc));
588     CHECK(slot == 370000000000ll + amount);
589 }
590
591 void testStoreSubLoad(int amount)
592 {
593     Procedure proc;
594     BasicBlock* root = proc.addBlock();
595     int32_t startValue = std::numeric_limits<int32_t>::min();
596     int32_t slot = startValue;
597     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
598     root->appendNew<MemoryValue>(
599         proc, Store, Origin(),
600         root->appendNew<Value>(
601             proc, Sub, Origin(),
602             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
603             root->appendNew<Value>(
604                 proc, Trunc, Origin(),
605                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
606         slotPtr, 0);
607     root->appendNewControlValue(
608         proc, Return, Origin(),
609         root->appendNew<Const32Value>(proc, Origin(), 0));
610
611     CHECK(!compileAndRun<int>(proc, amount));
612     CHECK(slot == startValue - amount);
613 }
614
615 void testStoreAddLoadInterference(int amount)
616 {
617     Procedure proc;
618     BasicBlock* root = proc.addBlock();
619     int slot = 37;
620     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
621     ArgumentRegValue* otherSlotPtr =
622         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
623     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr);
624     root->appendNew<MemoryValue>(
625         proc, Store, Origin(),
626         root->appendNew<Const32Value>(proc, Origin(), 666),
627         otherSlotPtr, 0);
628     root->appendNew<MemoryValue>(
629         proc, Store, Origin(),
630         root->appendNew<Value>(
631             proc, Add, Origin(),
632             load, root->appendNew<Const32Value>(proc, Origin(), amount)),
633         slotPtr, 0);
634     root->appendNewControlValue(
635         proc, Return, Origin(),
636         root->appendNew<Const32Value>(proc, Origin(), 0));
637
638     CHECK(!compileAndRun<int>(proc, &slot));
639     CHECK(slot == 37 + amount);
640 }
641
642 void testStoreAddAndLoad(int amount, int mask)
643 {
644     Procedure proc;
645     BasicBlock* root = proc.addBlock();
646     int slot = 37;
647     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
648     root->appendNew<MemoryValue>(
649         proc, Store, Origin(),
650         root->appendNew<Value>(
651             proc, BitAnd, Origin(),
652             root->appendNew<Value>(
653                 proc, Add, Origin(),
654                 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
655                 root->appendNew<Const32Value>(proc, Origin(), amount)),
656             root->appendNew<Const32Value>(proc, Origin(), mask)),
657         slotPtr, 0);
658     root->appendNewControlValue(
659         proc, Return, Origin(),
660         root->appendNew<Const32Value>(proc, Origin(), 0));
661
662     CHECK(!compileAndRun<int>(proc));
663     CHECK(slot == ((37 + amount) & mask));
664 }
665
666 void testStoreNegLoad32(int32_t value)
667 {
668     Procedure proc;
669     BasicBlock* root = proc.addBlock();
670
671     int32_t slot = value;
672
673     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
674
675     root->appendNew<MemoryValue>(
676         proc, Store, Origin(),
677         root->appendNew<Value>(
678             proc, Sub, Origin(),
679             root->appendNew<Const32Value>(proc, Origin(), 0),
680             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)),
681         slotPtr, 0);
682
683     root->appendNewControlValue(
684         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
685
686     CHECK(!compileAndRun<int32_t>(proc));
687     CHECK(slot == -value);
688 }
689
690 void testStoreNegLoadPtr(intptr_t value)
691 {
692     Procedure proc;
693     BasicBlock* root = proc.addBlock();
694
695     intptr_t slot = value;
696
697     ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
698
699     root->appendNew<MemoryValue>(
700         proc, Store, Origin(),
701         root->appendNew<Value>(
702             proc, Sub, Origin(),
703             root->appendNew<ConstPtrValue>(proc, Origin(), 0),
704             root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)),
705         slotPtr, 0);
706
707     root->appendNewControlValue(
708         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
709
710     CHECK(!compileAndRun<int32_t>(proc));
711     CHECK(slot == -value);
712 }
713
714 void testAdd1Uncommuted(int value)
715 {
716     Procedure proc;
717     BasicBlock* root = proc.addBlock();
718     root->appendNewControlValue(
719         proc, Return, Origin(),
720         root->appendNew<Value>(
721             proc, Add, Origin(),
722             root->appendNew<Const32Value>(proc, Origin(), 1),
723             root->appendNew<Value>(
724                 proc, Trunc, Origin(),
725                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
726
727     CHECK(compileAndRun<int>(proc, value) == value + 1);
728 }
729
730 void testLoadOffset()
731 {
732     Procedure proc;
733     BasicBlock* root = proc.addBlock();
734     int array[] = { 1, 2 };
735     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
736     root->appendNewControlValue(
737         proc, Return, Origin(),
738         root->appendNew<Value>(
739             proc, Add, Origin(),
740             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
741             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int)))));
742
743     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
744 }
745
746 void testLoadOffsetNotConstant()
747 {
748     Procedure proc;
749     BasicBlock* root = proc.addBlock();
750     int array[] = { 1, 2 };
751     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
752     root->appendNewControlValue(
753         proc, Return, Origin(),
754         root->appendNew<Value>(
755             proc, Add, Origin(),
756             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
757             root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int)))));
758
759     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
760 }
761
762 void testLoadOffsetUsingAdd()
763 {
764     Procedure proc;
765     BasicBlock* root = proc.addBlock();
766     int array[] = { 1, 2 };
767     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
768     root->appendNewControlValue(
769         proc, Return, Origin(),
770         root->appendNew<Value>(
771             proc, Add, Origin(),
772             root->appendNew<MemoryValue>(
773                 proc, Load, Int32, Origin(),
774                 root->appendNew<Value>(
775                     proc, Add, Origin(), arrayPtr,
776                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
777             root->appendNew<MemoryValue>(
778                 proc, Load, Int32, Origin(),
779                 root->appendNew<Value>(
780                     proc, Add, Origin(), arrayPtr,
781                     root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))))));
782
783     CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
784 }
785
786 void testLoadOffsetUsingAddInterference()
787 {
788     Procedure proc;
789     BasicBlock* root = proc.addBlock();
790     int array[] = { 1, 2 };
791     ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
792     ArgumentRegValue* otherArrayPtr =
793         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
794     Const32Value* theNumberOfTheBeast = root->appendNew<Const32Value>(proc, Origin(), 666);
795     MemoryValue* left = root->appendNew<MemoryValue>(
796         proc, Load, Int32, Origin(),
797         root->appendNew<Value>(
798             proc, Add, Origin(), arrayPtr,
799             root->appendNew<ConstPtrValue>(proc, Origin(), 0)));
800     MemoryValue* right = root->appendNew<MemoryValue>(
801         proc, Load, Int32, Origin(),
802         root->appendNew<Value>(
803             proc, Add, Origin(), arrayPtr,
804             root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))));
805     root->appendNew<MemoryValue>(
806         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0);
807     root->appendNew<MemoryValue>(
808         proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, static_cast<int32_t>(sizeof(int)));
809     root->appendNewControlValue(
810         proc, Return, Origin(),
811         root->appendNew<Value>(
812             proc, Add, Origin(), left, right));
813
814     CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2);
815     CHECK(array[0] == 666);
816     CHECK(array[1] == 666);
817 }
818
819 void testLoadOffsetUsingAddNotConstant()
820 {
821     Procedure proc;
822     BasicBlock* root = proc.addBlock();
823     int array[] = { 1, 2 };
824     Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
825     root->appendNewControlValue(
826         proc, Return, Origin(),
827         root->appendNew<Value>(
828             proc, Add, Origin(),
829             root->appendNew<MemoryValue>(
830                 proc, Load, Int32, Origin(),
831                 root->appendNew<Value>(
832                     proc, Add, Origin(), arrayPtr,
833                     root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
834             root->appendNew<MemoryValue>(
835                 proc, Load, Int32, Origin(),
836                 root->appendNew<Value>(
837                     proc, Add, Origin(), arrayPtr,
838                     root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))))));
839
840     CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
841 }
842
843 void testLoadAddrShift(unsigned shift)
844 {
845     Procedure proc;
846     BasicBlock* root = proc.addBlock();
847     int slots[2];
848
849     // Figure out which slot to use while having proper alignment for the shift.
850     int* slot;
851     uintptr_t arg;
852     for (unsigned i = sizeof(slots)/sizeof(slots[0]); i--;) {
853         slot = slots + i;
854         arg = bitwise_cast<uintptr_t>(slot) >> shift;
855         if (bitwise_cast<int*>(arg << shift) == slot)
856             break;
857     }
858
859     *slot = 8675309;
860
861     root->appendNewControlValue(
862         proc, Return, Origin(),
863         root->appendNew<MemoryValue>(
864             proc, Load, Int32, Origin(),
865             root->appendNew<Value>(
866                 proc, Shl, Origin(),
867                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
868                 root->appendNew<Const32Value>(proc, Origin(), shift))));
869
870     CHECK(compileAndRun<int>(proc, arg) == 8675309);
871 }
872
873 void testFramePointer()
874 {
875     Procedure proc;
876     BasicBlock* root = proc.addBlock();
877     root->appendNewControlValue(
878         proc, Return, Origin(),
879         root->appendNew<Value>(proc, FramePointer, Origin()));
880
881     void* fp = compileAndRun<void*>(proc);
882     CHECK(fp < &proc);
883     CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
884 }
885
886 void testOverrideFramePointer()
887 {
888     {
889         Procedure proc;
890         BasicBlock* root = proc.addBlock();
891
892         // Add a stack slot to make the frame non trivial.
893         root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
894
895         // Sub on x86 UseDef the source. If FP is not protected correctly, it will be overridden since it is the last visible use.
896         Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
897         Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
898         Value* result = root->appendNew<Value>(proc, Sub, Origin(), fp, offset);
899
900         root->appendNewControlValue(proc, Return, Origin(), result);
901         CHECK(compileAndRun<int64_t>(proc, 1));
902     }
903     {
904         Procedure proc;
905         BasicBlock* root = proc.addBlock();
906
907         root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
908
909         Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
910         Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
911         Value* offsetFP = root->appendNew<Value>(proc, BitAnd, Origin(), offset, fp);
912         Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
913         Value* offsetArg = root->appendNew<Value>(proc, Add, Origin(), offset, arg);
914         Value* result = root->appendNew<Value>(proc, Add, Origin(), offsetArg, offsetFP);
915
916         root->appendNewControlValue(proc, Return, Origin(), result);
917         CHECK(compileAndRun<int64_t>(proc, 1, 2));
918     }
919 }
920
921 void testStackSlot()
922 {
923     Procedure proc;
924     BasicBlock* root = proc.addBlock();
925     root->appendNewControlValue(
926         proc, Return, Origin(),
927         root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(1)));
928
929     void* stackSlot = compileAndRun<void*>(proc);
930     CHECK(stackSlot < &proc);
931     CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000);
932 }
933
934 void testLoadFromFramePointer()
935 {
936     Procedure proc;
937     BasicBlock* root = proc.addBlock();
938     root->appendNewControlValue(
939         proc, Return, Origin(),
940         root->appendNew<MemoryValue>(
941             proc, Load, pointerType(), Origin(),
942             root->appendNew<Value>(proc, FramePointer, Origin())));
943
944     void* fp = compileAndRun<void*>(proc);
945     void* myFP = __builtin_frame_address(0);
946     CHECK(fp <= myFP);
947     CHECK(fp >= bitwise_cast<char*>(myFP) - 10000);
948 }
949
950 void testStoreLoadStackSlot(int value)
951 {
952     Procedure proc;
953     BasicBlock* root = proc.addBlock();
954
955     SlotBaseValue* stack =
956         root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(sizeof(int)));
957
958     root->appendNew<MemoryValue>(
959         proc, Store, Origin(),
960         root->appendNew<Value>(
961             proc, Trunc, Origin(),
962             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
963         stack, 0);
964
965     root->appendNewControlValue(
966         proc, Return, Origin(),
967         root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack));
968
969     CHECK(compileAndRun<int>(proc, value) == value);
970 }
971
972 void testStoreFloat(double input)
973 {
974     // Simple store from an address in a register.
975     {
976         Procedure proc;
977         BasicBlock* root = proc.addBlock();
978         Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
979         Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
980
981         Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
982         root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
983
984         root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
985
986         float output = 0.;
987         CHECK(!compileAndRun<int64_t>(proc, input, &output));
988         CHECK(isIdentical(static_cast<float>(input), output));
989     }
990
991     // Simple indexed store.
992     {
993         Procedure proc;
994         BasicBlock* root = proc.addBlock();
995         Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
996         Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
997
998         Value* destinationBaseAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
999         Value* index = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1000         Value* scaledIndex = root->appendNew<Value>(
1001             proc, Shl, Origin(),
1002             index,
1003             root->appendNew<Const32Value>(proc, Origin(), 2));
1004         Value* destinationAddress = root->appendNew<Value>(proc, Add, Origin(), scaledIndex, destinationBaseAddress);
1005
1006         root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
1007
1008         root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1009
1010         float output = 0.;
1011         CHECK(!compileAndRun<int64_t>(proc, input, &output - 1, 1));
1012         CHECK(isIdentical(static_cast<float>(input), output));
1013     }
1014 }
1015
1016 void testStoreDoubleConstantAsFloat(double input)
1017 {
1018     // Simple store from an address in a register.
1019     Procedure proc;
1020     BasicBlock* root = proc.addBlock();
1021     Value* value = root->appendNew<ConstDoubleValue>(proc, Origin(), input);
1022     Value* valueAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), value);
1023
1024     Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1025
1026     root->appendNew<MemoryValue>(proc, Store, Origin(), valueAsFloat, destinationAddress);
1027
1028     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1029
1030     float output = 0.;
1031     CHECK(!compileAndRun<int64_t>(proc, input, &output));
1032     CHECK(isIdentical(static_cast<float>(input), output));
1033 }
1034
1035 void testSpillGP()
1036 {
1037     Procedure proc;
1038     BasicBlock* root = proc.addBlock();
1039
1040     Vector<Value*> sources;
1041     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1042     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1043
1044     for (unsigned i = 0; i < 30; ++i) {
1045         sources.append(
1046             root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
1047         );
1048     }
1049
1050     Value* total = root->appendNew<Const64Value>(proc, Origin(), 0);
1051     for (Value* value : sources)
1052         total = root->appendNew<Value>(proc, Add, Origin(), total, value);
1053
1054     root->appendNewControlValue(proc, Return, Origin(), total);
1055     compileAndRun<int>(proc, 1, 2);
1056 }
1057
1058 void testSpillFP()
1059 {
1060     Procedure proc;
1061     BasicBlock* root = proc.addBlock();
1062
1063     Vector<Value*> sources;
1064     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1065     sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
1066
1067     for (unsigned i = 0; i < 30; ++i) {
1068         sources.append(
1069             root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
1070         );
1071     }
1072
1073     Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1074     for (Value* value : sources)
1075         total = root->appendNew<Value>(proc, Add, Origin(), total, value);
1076
1077     root->appendNewControlValue(proc, Return, Origin(), total);
1078     compileAndRun<double>(proc, 1.1, 2.5);
1079 }
1080
1081 void testInt32ToDoublePartialRegisterStall()
1082 {
1083     Procedure proc;
1084     BasicBlock* root = proc.addBlock();
1085     BasicBlock* loop = proc.addBlock();
1086     BasicBlock* done = proc.addBlock();
1087
1088     // Head.
1089     Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1090     Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1091     UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
1092     UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
1093     root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
1094
1095     // Loop.
1096     Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
1097     Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
1098     originalCounter->setPhi(loopCounter);
1099     originalTotal->setPhi(loopTotal);
1100
1101     Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
1102     Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
1103     Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
1104     UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
1105     updatedTotalUpsilon->setPhi(loopTotal);
1106
1107     Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
1108     UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
1109     decCounterUpsilon->setPhi(loopCounter);
1110     loop->appendNewControlValue(
1111         proc, Branch, Origin(),
1112         decCounter,
1113         FrequentedBlock(loop), FrequentedBlock(done));
1114
1115     // Tail.
1116     done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
1117     CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
1118 }
1119
1120 void testInt32ToDoublePartialRegisterWithoutStall()
1121 {
1122     Procedure proc;
1123     BasicBlock* root = proc.addBlock();
1124     BasicBlock* loop = proc.addBlock();
1125     BasicBlock* done = proc.addBlock();
1126
1127     // Head.
1128     Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1129     Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1130     UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
1131     UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
1132     uint64_t forPaddingInput;
1133     Value* forPaddingInputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingInput);
1134     uint64_t forPaddingOutput;
1135     Value* forPaddingOutputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingOutput);
1136     root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
1137
1138     // Loop.
1139     Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
1140     Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
1141     originalCounter->setPhi(loopCounter);
1142     originalTotal->setPhi(loopTotal);
1143
1144     Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
1145     Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
1146     Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
1147
1148     // Add enough padding instructions to avoid a stall.
1149     Value* loadPadding = loop->appendNew<MemoryValue>(proc, Load, Int64, Origin(), forPaddingInputAddress);
1150     Value* padding = loop->appendNew<Value>(proc, BitXor, Origin(), loadPadding, loopCounter);
1151     padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
1152     padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
1153     padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
1154     padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
1155     padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
1156     padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
1157     padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
1158     padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
1159     padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
1160     padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
1161     padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
1162     loop->appendNew<MemoryValue>(proc, Store, Origin(), padding, forPaddingOutputAddress);
1163
1164     UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
1165     updatedTotalUpsilon->setPhi(loopTotal);
1166
1167     Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
1168     UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
1169     decCounterUpsilon->setPhi(loopCounter);
1170     loop->appendNewControlValue(
1171         proc, Branch, Origin(),
1172         decCounter,
1173         FrequentedBlock(loop), FrequentedBlock(done));
1174
1175     // Tail.
1176     done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
1177     CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
1178 }
1179
1180 void testBranch()
1181 {
1182     Procedure proc;
1183     BasicBlock* root = proc.addBlock();
1184     BasicBlock* thenCase = proc.addBlock();
1185     BasicBlock* elseCase = proc.addBlock();
1186
1187     root->appendNewControlValue(
1188         proc, Branch, Origin(),
1189         root->appendNew<Value>(
1190             proc, Trunc, Origin(),
1191             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1192         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1193
1194     thenCase->appendNewControlValue(
1195         proc, Return, Origin(),
1196         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1197
1198     elseCase->appendNewControlValue(
1199         proc, Return, Origin(),
1200         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1201
1202     auto code = compileProc(proc);
1203     CHECK(invoke<int>(*code, 42) == 1);
1204     CHECK(invoke<int>(*code, 0) == 0);
1205 }
1206
1207 void testBranchPtr()
1208 {
1209     Procedure proc;
1210     BasicBlock* root = proc.addBlock();
1211     BasicBlock* thenCase = proc.addBlock();
1212     BasicBlock* elseCase = proc.addBlock();
1213
1214     root->appendNewControlValue(
1215         proc, Branch, Origin(),
1216         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1217         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1218
1219     thenCase->appendNewControlValue(
1220         proc, Return, Origin(),
1221         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1222
1223     elseCase->appendNewControlValue(
1224         proc, Return, Origin(),
1225         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1226
1227     auto code = compileProc(proc);
1228     CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1);
1229     CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0);
1230 }
1231
1232 void testDiamond()
1233 {
1234     Procedure proc;
1235     BasicBlock* root = proc.addBlock();
1236     BasicBlock* thenCase = proc.addBlock();
1237     BasicBlock* elseCase = proc.addBlock();
1238     BasicBlock* done = proc.addBlock();
1239
1240     root->appendNewControlValue(
1241         proc, Branch, Origin(),
1242         root->appendNew<Value>(
1243             proc, Trunc, Origin(),
1244             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1245         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1246
1247     UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
1248         proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1249     thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1250
1251     UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
1252         proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1253     elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1254
1255     Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
1256     thenResult->setPhi(phi);
1257     elseResult->setPhi(phi);
1258     done->appendNewControlValue(proc, Return, Origin(), phi);
1259
1260     auto code = compileProc(proc);
1261     CHECK(invoke<int>(*code, 42) == 1);
1262     CHECK(invoke<int>(*code, 0) == 0);
1263 }
1264
1265 void testBranchNotEqual()
1266 {
1267     Procedure proc;
1268     BasicBlock* root = proc.addBlock();
1269     BasicBlock* thenCase = proc.addBlock();
1270     BasicBlock* elseCase = proc.addBlock();
1271
1272     root->appendNewControlValue(
1273         proc, Branch, Origin(),
1274         root->appendNew<Value>(
1275             proc, NotEqual, Origin(),
1276             root->appendNew<Value>(
1277                 proc, Trunc, Origin(),
1278                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1279             root->appendNew<Const32Value>(proc, Origin(), 0)),
1280         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1281
1282     thenCase->appendNewControlValue(
1283         proc, Return, Origin(),
1284         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1285
1286     elseCase->appendNewControlValue(
1287         proc, Return, Origin(),
1288         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1289
1290     auto code = compileProc(proc);
1291     CHECK(invoke<int>(*code, 42) == 1);
1292     CHECK(invoke<int>(*code, 0) == 0);
1293 }
1294
1295 void testBranchNotEqualCommute()
1296 {
1297     Procedure proc;
1298     BasicBlock* root = proc.addBlock();
1299     BasicBlock* thenCase = proc.addBlock();
1300     BasicBlock* elseCase = proc.addBlock();
1301
1302     root->appendNewControlValue(
1303         proc, Branch, Origin(),
1304         root->appendNew<Value>(
1305             proc, NotEqual, Origin(),
1306             root->appendNew<Const32Value>(proc, Origin(), 0),
1307             root->appendNew<Value>(
1308                 proc, Trunc, Origin(),
1309                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
1310         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1311
1312     thenCase->appendNewControlValue(
1313         proc, Return, Origin(),
1314         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1315
1316     elseCase->appendNewControlValue(
1317         proc, Return, Origin(),
1318         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1319
1320     auto code = compileProc(proc);
1321     CHECK(invoke<int>(*code, 42) == 1);
1322     CHECK(invoke<int>(*code, 0) == 0);
1323 }
1324
1325 void testBranchNotEqualNotEqual()
1326 {
1327     Procedure proc;
1328     BasicBlock* root = proc.addBlock();
1329     BasicBlock* thenCase = proc.addBlock();
1330     BasicBlock* elseCase = proc.addBlock();
1331
1332     root->appendNewControlValue(
1333         proc, Branch, Origin(),
1334         root->appendNew<Value>(
1335             proc, NotEqual, Origin(),
1336             root->appendNew<Value>(
1337                 proc, NotEqual, Origin(),
1338                 root->appendNew<Value>(
1339                     proc, Trunc, Origin(),
1340                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1341                 root->appendNew<Const32Value>(proc, Origin(), 0)),
1342             root->appendNew<Const32Value>(proc, Origin(), 0)),
1343         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1344
1345     thenCase->appendNewControlValue(
1346         proc, Return, Origin(),
1347         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1348
1349     elseCase->appendNewControlValue(
1350         proc, Return, Origin(),
1351         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1352
1353     auto code = compileProc(proc);
1354     CHECK(invoke<int>(*code, 42) == 1);
1355     CHECK(invoke<int>(*code, 0) == 0);
1356 }
1357
1358 void testBranchEqual()
1359 {
1360     Procedure proc;
1361     BasicBlock* root = proc.addBlock();
1362     BasicBlock* thenCase = proc.addBlock();
1363     BasicBlock* elseCase = proc.addBlock();
1364
1365     root->appendNewControlValue(
1366         proc, Branch, Origin(),
1367         root->appendNew<Value>(
1368             proc, Equal, Origin(),
1369             root->appendNew<Value>(
1370                 proc, Trunc, Origin(),
1371                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1372             root->appendNew<Const32Value>(proc, Origin(), 0)),
1373         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1374
1375     thenCase->appendNewControlValue(
1376         proc, Return, Origin(),
1377         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1378
1379     elseCase->appendNewControlValue(
1380         proc, Return, Origin(),
1381         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1382
1383     auto code = compileProc(proc);
1384     CHECK(invoke<int>(*code, 42) == 1);
1385     CHECK(invoke<int>(*code, 0) == 0);
1386 }
1387
1388 void testBranchEqualEqual()
1389 {
1390     Procedure proc;
1391     BasicBlock* root = proc.addBlock();
1392     BasicBlock* thenCase = proc.addBlock();
1393     BasicBlock* elseCase = proc.addBlock();
1394
1395     root->appendNewControlValue(
1396         proc, Branch, Origin(),
1397         root->appendNew<Value>(
1398             proc, Equal, Origin(),
1399             root->appendNew<Value>(
1400                 proc, Equal, Origin(),
1401                 root->appendNew<Value>(
1402                     proc, Trunc, Origin(),
1403                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1404                 root->appendNew<Const32Value>(proc, Origin(), 0)),
1405             root->appendNew<Const32Value>(proc, Origin(), 0)),
1406         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1407
1408     thenCase->appendNewControlValue(
1409         proc, Return, Origin(),
1410         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1411
1412     elseCase->appendNewControlValue(
1413         proc, Return, Origin(),
1414         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1415
1416     auto code = compileProc(proc);
1417     CHECK(invoke<int>(*code, 42) == 1);
1418     CHECK(invoke<int>(*code, 0) == 0);
1419 }
1420
1421 void testBranchEqualCommute()
1422 {
1423     Procedure proc;
1424     BasicBlock* root = proc.addBlock();
1425     BasicBlock* thenCase = proc.addBlock();
1426     BasicBlock* elseCase = proc.addBlock();
1427
1428     root->appendNewControlValue(
1429         proc, Branch, Origin(),
1430         root->appendNew<Value>(
1431             proc, Equal, Origin(),
1432             root->appendNew<Const32Value>(proc, Origin(), 0),
1433             root->appendNew<Value>(
1434                 proc, Trunc, Origin(),
1435                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
1436         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1437
1438     thenCase->appendNewControlValue(
1439         proc, Return, Origin(),
1440         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1441
1442     elseCase->appendNewControlValue(
1443         proc, Return, Origin(),
1444         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1445
1446     auto code = compileProc(proc);
1447     CHECK(invoke<int>(*code, 42) == 1);
1448     CHECK(invoke<int>(*code, 0) == 0);
1449 }
1450
1451 void testBranchEqualEqual1()
1452 {
1453     Procedure proc;
1454     BasicBlock* root = proc.addBlock();
1455     BasicBlock* thenCase = proc.addBlock();
1456     BasicBlock* elseCase = proc.addBlock();
1457
1458     root->appendNewControlValue(
1459         proc, Branch, Origin(),
1460         root->appendNew<Value>(
1461             proc, Equal, Origin(),
1462             root->appendNew<Value>(
1463                 proc, Equal, Origin(),
1464                 root->appendNew<Value>(
1465                     proc, Trunc, Origin(),
1466                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1467                 root->appendNew<Const32Value>(proc, Origin(), 0)),
1468             root->appendNew<Const32Value>(proc, Origin(), 1)),
1469         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1470
1471     thenCase->appendNewControlValue(
1472         proc, Return, Origin(),
1473         thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1474
1475     elseCase->appendNewControlValue(
1476         proc, Return, Origin(),
1477         elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1478
1479     auto code = compileProc(proc);
1480     CHECK(invoke<int>(*code, 42) == 1);
1481     CHECK(invoke<int>(*code, 0) == 0);
1482 }
1483
1484 void testBranchEqualOrUnorderedArgs(double a, double b)
1485 {
1486     Procedure proc;
1487     BasicBlock* root = proc.addBlock();
1488     BasicBlock* thenCase = proc.addBlock();
1489     BasicBlock* elseCase = proc.addBlock();
1490
1491     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1492     Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1493     root->appendNewControlValue(
1494         proc, Branch, Origin(),
1495         root->appendNew<Value>(
1496             proc, EqualOrUnordered, Origin(),
1497             argumentA,
1498             argumentB),
1499         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1500
1501     thenCase->appendNewControlValue(
1502         proc, Return, Origin(),
1503         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1504
1505     elseCase->appendNewControlValue(
1506         proc, Return, Origin(),
1507         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1508
1509     int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1510     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
1511 }
1512
1513 void testBranchEqualOrUnorderedArgs(float a, float b)
1514 {
1515     Procedure proc;
1516     BasicBlock* root = proc.addBlock();
1517     BasicBlock* thenCase = proc.addBlock();
1518     BasicBlock* elseCase = proc.addBlock();
1519
1520     Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1521         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1522     Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1523         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1524
1525     root->appendNewControlValue(
1526         proc, Branch, Origin(),
1527         root->appendNew<Value>(
1528             proc, EqualOrUnordered, Origin(),
1529             argumentA,
1530             argumentB),
1531         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1532
1533     thenCase->appendNewControlValue(
1534         proc, Return, Origin(),
1535         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1536
1537     elseCase->appendNewControlValue(
1538         proc, Return, Origin(),
1539         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1540
1541     int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1542     CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1543 }
1544
1545 void testBranchNotEqualAndOrderedArgs(double a, double b)
1546 {
1547     Procedure proc;
1548     BasicBlock* root = proc.addBlock();
1549     BasicBlock* thenCase = proc.addBlock();
1550     BasicBlock* elseCase = proc.addBlock();
1551
1552     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1553     Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1554     Value* equalOrUnordered = root->appendNew<Value>(
1555         proc, EqualOrUnordered, Origin(),
1556         argumentA,
1557         argumentB);
1558     Value* notEqualAndOrdered = root->appendNew<Value>(
1559         proc, Equal, Origin(),
1560         root->appendNew<Const32Value>(proc, Origin(), 0),
1561         equalOrUnordered);
1562     root->appendNewControlValue(
1563         proc, Branch, Origin(),
1564         notEqualAndOrdered,
1565         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1566
1567     thenCase->appendNewControlValue(
1568         proc, Return, Origin(),
1569         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1570
1571     elseCase->appendNewControlValue(
1572         proc, Return, Origin(),
1573         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1574
1575     int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
1576     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
1577 }
1578
1579 void testBranchNotEqualAndOrderedArgs(float a, float b)
1580 {
1581     Procedure proc;
1582     BasicBlock* root = proc.addBlock();
1583     BasicBlock* thenCase = proc.addBlock();
1584     BasicBlock* elseCase = proc.addBlock();
1585
1586     Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1587         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1588     Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1589         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1590     Value* equalOrUnordered = root->appendNew<Value>(
1591         proc, EqualOrUnordered, Origin(),
1592         argumentA,
1593         argumentB);
1594     Value* notEqualAndOrdered = root->appendNew<Value>(
1595         proc, Equal, Origin(),
1596         root->appendNew<Const32Value>(proc, Origin(), 0),
1597         equalOrUnordered);
1598     root->appendNewControlValue(
1599         proc, Branch, Origin(),
1600         notEqualAndOrdered,
1601         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1602
1603     thenCase->appendNewControlValue(
1604         proc, Return, Origin(),
1605         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1606
1607     elseCase->appendNewControlValue(
1608         proc, Return, Origin(),
1609         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1610
1611     int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
1612     CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1613 }
1614
1615 void testBranchEqualOrUnorderedDoubleArgImm(double a, double b)
1616 {
1617     Procedure proc;
1618     BasicBlock* root = proc.addBlock();
1619     BasicBlock* thenCase = proc.addBlock();
1620     BasicBlock* elseCase = proc.addBlock();
1621
1622     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1623     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1624     root->appendNewControlValue(
1625         proc, Branch, Origin(),
1626         root->appendNew<Value>(
1627             proc, EqualOrUnordered, Origin(),
1628             argumentA,
1629             argumentB),
1630         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1631
1632     thenCase->appendNewControlValue(
1633         proc, Return, Origin(),
1634         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1635
1636     elseCase->appendNewControlValue(
1637         proc, Return, Origin(),
1638         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1639
1640     int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1641     CHECK(compileAndRun<int64_t>(proc, a) == expected);
1642 }
1643
1644 void testBranchEqualOrUnorderedFloatArgImm(float a, float b)
1645 {
1646     Procedure proc;
1647     BasicBlock* root = proc.addBlock();
1648     BasicBlock* thenCase = proc.addBlock();
1649     BasicBlock* elseCase = proc.addBlock();
1650
1651     Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1652         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1653     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1654
1655     root->appendNewControlValue(
1656         proc, Branch, Origin(),
1657         root->appendNew<Value>(
1658             proc, EqualOrUnordered, Origin(),
1659             argumentA,
1660             argumentB),
1661         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1662
1663     thenCase->appendNewControlValue(
1664         proc, Return, Origin(),
1665         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1666
1667     elseCase->appendNewControlValue(
1668         proc, Return, Origin(),
1669         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1670
1671     int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1672     CHECK(compileAndRun<int64_t>(proc, &a) == expected);
1673 }
1674
1675 void testBranchEqualOrUnorderedDoubleImms(double a, double b)
1676 {
1677     Procedure proc;
1678     BasicBlock* root = proc.addBlock();
1679     BasicBlock* thenCase = proc.addBlock();
1680     BasicBlock* elseCase = proc.addBlock();
1681
1682     Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1683     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1684     root->appendNewControlValue(
1685         proc, Branch, Origin(),
1686         root->appendNew<Value>(
1687             proc, EqualOrUnordered, Origin(),
1688             argumentA,
1689             argumentB),
1690         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1691
1692     thenCase->appendNewControlValue(
1693         proc, Return, Origin(),
1694         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1695
1696     elseCase->appendNewControlValue(
1697         proc, Return, Origin(),
1698         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1699
1700     int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1701     CHECK(compileAndRun<int64_t>(proc) == expected);
1702 }
1703
1704 void testBranchEqualOrUnorderedFloatImms(float a, float b)
1705 {
1706     Procedure proc;
1707     BasicBlock* root = proc.addBlock();
1708     BasicBlock* thenCase = proc.addBlock();
1709     BasicBlock* elseCase = proc.addBlock();
1710
1711     Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1712     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1713
1714     root->appendNewControlValue(
1715         proc, Branch, Origin(),
1716         root->appendNew<Value>(
1717             proc, EqualOrUnordered, Origin(),
1718             argumentA,
1719             argumentB),
1720         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1721
1722     thenCase->appendNewControlValue(
1723         proc, Return, Origin(),
1724         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1725
1726     elseCase->appendNewControlValue(
1727         proc, Return, Origin(),
1728         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1729
1730     int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1731     CHECK(compileAndRun<int64_t>(proc) == expected);
1732 }
1733
1734 void testBranchEqualOrUnorderedFloatWithUselessDoubleConversion(float a, float b)
1735 {
1736     Procedure proc;
1737     BasicBlock* root = proc.addBlock();
1738     BasicBlock* thenCase = proc.addBlock();
1739     BasicBlock* elseCase = proc.addBlock();
1740
1741     Value* argument1 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1742         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1743     Value* argument2 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1744         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1745     Value* argument1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument1);
1746     Value* argument2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument2);
1747
1748     root->appendNewControlValue(
1749         proc, Branch, Origin(),
1750         root->appendNew<Value>(
1751             proc, EqualOrUnordered, Origin(),
1752             argument1AsDouble,
1753             argument2AsDouble),
1754         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1755
1756     thenCase->appendNewControlValue(
1757         proc, Return, Origin(),
1758         thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1759
1760     elseCase->appendNewControlValue(
1761         proc, Return, Origin(),
1762         elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1763
1764     int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1765     CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1766 }
1767
1768 void testBranchFold(int value)
1769 {
1770     Procedure proc;
1771     BasicBlock* root = proc.addBlock();
1772     BasicBlock* thenCase = proc.addBlock();
1773     BasicBlock* elseCase = proc.addBlock();
1774
1775     root->appendNewControlValue(
1776         proc, Branch, Origin(),
1777         root->appendNew<Const32Value>(proc, Origin(), value),
1778         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1779
1780     thenCase->appendNewControlValue(
1781         proc, Return, Origin(),
1782         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1783
1784     elseCase->appendNewControlValue(
1785         proc, Return, Origin(),
1786         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1787
1788     CHECK(compileAndRun<int>(proc) == !!value);
1789 }
1790
1791 void testDiamondFold(int value)
1792 {
1793     Procedure proc;
1794     BasicBlock* root = proc.addBlock();
1795     BasicBlock* thenCase = proc.addBlock();
1796     BasicBlock* elseCase = proc.addBlock();
1797     BasicBlock* done = proc.addBlock();
1798
1799     root->appendNewControlValue(
1800         proc, Branch, Origin(),
1801         root->appendNew<Const32Value>(proc, Origin(), value),
1802         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1803
1804     UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
1805         proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1806     thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1807
1808     UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
1809         proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1810     elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1811
1812     Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
1813     thenResult->setPhi(phi);
1814     elseResult->setPhi(phi);
1815     done->appendNewControlValue(proc, Return, Origin(), phi);
1816
1817     CHECK(compileAndRun<int>(proc) == !!value);
1818 }
1819
1820 void testBranchNotEqualFoldPtr(intptr_t value)
1821 {
1822     Procedure proc;
1823     BasicBlock* root = proc.addBlock();
1824     BasicBlock* thenCase = proc.addBlock();
1825     BasicBlock* elseCase = proc.addBlock();
1826
1827     root->appendNewControlValue(
1828         proc, Branch, Origin(),
1829         root->appendNew<Value>(
1830             proc, NotEqual, Origin(),
1831             root->appendNew<ConstPtrValue>(proc, Origin(), value),
1832             root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
1833         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1834
1835     thenCase->appendNewControlValue(
1836         proc, Return, Origin(),
1837         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1838
1839     elseCase->appendNewControlValue(
1840         proc, Return, Origin(),
1841         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1842
1843     CHECK(compileAndRun<int>(proc) == !!value);
1844 }
1845
1846 void testBranchEqualFoldPtr(intptr_t value)
1847 {
1848     Procedure proc;
1849     BasicBlock* root = proc.addBlock();
1850     BasicBlock* thenCase = proc.addBlock();
1851     BasicBlock* elseCase = proc.addBlock();
1852
1853     root->appendNewControlValue(
1854         proc, Branch, Origin(),
1855         root->appendNew<Value>(
1856             proc, Equal, Origin(),
1857             root->appendNew<ConstPtrValue>(proc, Origin(), value),
1858             root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
1859         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1860
1861     thenCase->appendNewControlValue(
1862         proc, Return, Origin(),
1863         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1864
1865     elseCase->appendNewControlValue(
1866         proc, Return, Origin(),
1867         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1868
1869     CHECK(compileAndRun<int>(proc) == !value);
1870 }
1871
1872 void testBranchLoadPtr()
1873 {
1874     Procedure proc;
1875     BasicBlock* root = proc.addBlock();
1876     BasicBlock* thenCase = proc.addBlock();
1877     BasicBlock* elseCase = proc.addBlock();
1878
1879     root->appendNewControlValue(
1880         proc, Branch, Origin(),
1881         root->appendNew<MemoryValue>(
1882             proc, Load, pointerType(), Origin(),
1883             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1884         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1885
1886     thenCase->appendNewControlValue(
1887         proc, Return, Origin(),
1888         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1889
1890     elseCase->appendNewControlValue(
1891         proc, Return, Origin(),
1892         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1893
1894     auto code = compileProc(proc);
1895     intptr_t cond;
1896     cond = 42;
1897     CHECK(invoke<int>(*code, &cond) == 1);
1898     cond = 0;
1899     CHECK(invoke<int>(*code, &cond) == 0);
1900 }
1901
1902 void testBranchLoad32()
1903 {
1904     Procedure proc;
1905     BasicBlock* root = proc.addBlock();
1906     BasicBlock* thenCase = proc.addBlock();
1907     BasicBlock* elseCase = proc.addBlock();
1908
1909     root->appendNewControlValue(
1910         proc, Branch, Origin(),
1911         root->appendNew<MemoryValue>(
1912             proc, Load, Int32, Origin(),
1913             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1914         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1915
1916     thenCase->appendNewControlValue(
1917         proc, Return, Origin(),
1918         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1919
1920     elseCase->appendNewControlValue(
1921         proc, Return, Origin(),
1922         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1923
1924     auto code = compileProc(proc);
1925     int32_t cond;
1926     cond = 42;
1927     CHECK(invoke<int>(*code, &cond) == 1);
1928     cond = 0;
1929     CHECK(invoke<int>(*code, &cond) == 0);
1930 }
1931
1932 void testBranchLoad8S()
1933 {
1934     Procedure proc;
1935     BasicBlock* root = proc.addBlock();
1936     BasicBlock* thenCase = proc.addBlock();
1937     BasicBlock* elseCase = proc.addBlock();
1938
1939     root->appendNewControlValue(
1940         proc, Branch, Origin(),
1941         root->appendNew<MemoryValue>(
1942             proc, Load8S, Origin(),
1943             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1944         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1945
1946     thenCase->appendNewControlValue(
1947         proc, Return, Origin(),
1948         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1949
1950     elseCase->appendNewControlValue(
1951         proc, Return, Origin(),
1952         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1953
1954     auto code = compileProc(proc);
1955     int8_t cond;
1956     cond = -1;
1957     CHECK(invoke<int>(*code, &cond) == 1);
1958     cond = 0;
1959     CHECK(invoke<int>(*code, &cond) == 0);
1960 }
1961
1962 void testBranchLoad8Z()
1963 {
1964     Procedure proc;
1965     BasicBlock* root = proc.addBlock();
1966     BasicBlock* thenCase = proc.addBlock();
1967     BasicBlock* elseCase = proc.addBlock();
1968
1969     root->appendNewControlValue(
1970         proc, Branch, Origin(),
1971         root->appendNew<MemoryValue>(
1972             proc, Load8Z, Origin(),
1973             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1974         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1975
1976     thenCase->appendNewControlValue(
1977         proc, Return, Origin(),
1978         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1979
1980     elseCase->appendNewControlValue(
1981         proc, Return, Origin(),
1982         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1983
1984     auto code = compileProc(proc);
1985     uint8_t cond;
1986     cond = 1;
1987     CHECK(invoke<int>(*code, &cond) == 1);
1988     cond = 0;
1989     CHECK(invoke<int>(*code, &cond) == 0);
1990 }
1991
1992 void testBranchLoad16S()
1993 {
1994     Procedure proc;
1995     BasicBlock* root = proc.addBlock();
1996     BasicBlock* thenCase = proc.addBlock();
1997     BasicBlock* elseCase = proc.addBlock();
1998
1999     root->appendNewControlValue(
2000         proc, Branch, Origin(),
2001         root->appendNew<MemoryValue>(
2002             proc, Load16S, Origin(),
2003             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2004         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2005
2006     thenCase->appendNewControlValue(
2007         proc, Return, Origin(),
2008         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2009
2010     elseCase->appendNewControlValue(
2011         proc, Return, Origin(),
2012         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2013
2014     auto code = compileProc(proc);
2015     int16_t cond;
2016     cond = -1;
2017     CHECK(invoke<int>(*code, &cond) == 1);
2018     cond = 0;
2019     CHECK(invoke<int>(*code, &cond) == 0);
2020 }
2021
2022 void testBranchLoad16Z()
2023 {
2024     Procedure proc;
2025     BasicBlock* root = proc.addBlock();
2026     BasicBlock* thenCase = proc.addBlock();
2027     BasicBlock* elseCase = proc.addBlock();
2028
2029     root->appendNewControlValue(
2030         proc, Branch, Origin(),
2031         root->appendNew<MemoryValue>(
2032             proc, Load16Z, Origin(),
2033             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2034         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2035
2036     thenCase->appendNewControlValue(
2037         proc, Return, Origin(),
2038         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2039
2040     elseCase->appendNewControlValue(
2041         proc, Return, Origin(),
2042         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2043
2044     auto code = compileProc(proc);
2045     uint16_t cond;
2046     cond = 1;
2047     CHECK(invoke<int>(*code, &cond) == 1);
2048     cond = 0;
2049     CHECK(invoke<int>(*code, &cond) == 0);
2050 }
2051
2052 void testBranch8WithLoad8ZIndex()
2053 {
2054     Procedure proc;
2055     BasicBlock* root = proc.addBlock();
2056     BasicBlock* thenCase = proc.addBlock();
2057     BasicBlock* elseCase = proc.addBlock();
2058
2059     int logScale = 1;
2060     root->appendNewControlValue(
2061         proc, Branch, Origin(),
2062         root->appendNew<Value>(
2063             proc, Above, Origin(),
2064             root->appendNew<MemoryValue>(
2065                 proc, Load8Z, Origin(),
2066                 root->appendNew<Value>(
2067                     proc, Add, Origin(),
2068                     root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2069                     root->appendNew<Value>(
2070                         proc, Shl, Origin(),
2071                         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
2072                         root->appendNew<Const32Value>(proc, Origin(), logScale)))),
2073             root->appendNew<Const32Value>(proc, Origin(), 250)),
2074         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2075
2076     thenCase->appendNewControlValue(
2077         proc, Return, Origin(),
2078         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2079
2080     elseCase->appendNewControlValue(
2081         proc, Return, Origin(),
2082         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2083
2084     auto code = compileProc(proc);
2085     uint32_t cond;
2086     cond = 0xffffffffU; // All bytes are 0xff.
2087     CHECK(invoke<int>(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 1);
2088     cond = 0x00000000U; // All bytes are 0.
2089     CHECK(invoke<int>(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 0);
2090 }
2091
2092 void testComplex(unsigned numVars, unsigned numConstructs)
2093 {
2094     MonotonicTime before = MonotonicTime::now();
2095
2096     Procedure proc;
2097     BasicBlock* current = proc.addBlock();
2098
2099     Const32Value* one = current->appendNew<Const32Value>(proc, Origin(), 1);
2100
2101     Vector<int32_t> varSlots;
2102     for (unsigned i = numVars; i--;)
2103         varSlots.append(i);
2104
2105     Vector<Value*> vars;
2106     for (int32_t& varSlot : varSlots) {
2107         Value* varSlotPtr = current->appendNew<ConstPtrValue>(proc, Origin(), &varSlot);
2108         vars.append(current->appendNew<MemoryValue>(proc, Load, Int32, Origin(), varSlotPtr));
2109     }
2110
2111     for (unsigned i = 0; i < numConstructs; ++i) {
2112         if (i & 1) {
2113             // Control flow diamond.
2114             unsigned predicateVarIndex = ((i >> 1) + 2) % numVars;
2115             unsigned thenIncVarIndex = ((i >> 1) + 0) % numVars;
2116             unsigned elseIncVarIndex = ((i >> 1) + 1) % numVars;
2117
2118             BasicBlock* thenBlock = proc.addBlock();
2119             BasicBlock* elseBlock = proc.addBlock();
2120             BasicBlock* continuation = proc.addBlock();
2121
2122             current->appendNewControlValue(
2123                 proc, Branch, Origin(), vars[predicateVarIndex],
2124                 FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
2125
2126             UpsilonValue* thenThenResult = thenBlock->appendNew<UpsilonValue>(
2127                 proc, Origin(),
2128                 thenBlock->appendNew<Value>(proc, Add, Origin(), vars[thenIncVarIndex], one));
2129             UpsilonValue* thenElseResult = thenBlock->appendNew<UpsilonValue>(
2130                 proc, Origin(), vars[elseIncVarIndex]);
2131             thenBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2132
2133             UpsilonValue* elseElseResult = elseBlock->appendNew<UpsilonValue>(
2134                 proc, Origin(),
2135                 elseBlock->appendNew<Value>(proc, Add, Origin(), vars[elseIncVarIndex], one));
2136             UpsilonValue* elseThenResult = elseBlock->appendNew<UpsilonValue>(
2137                 proc, Origin(), vars[thenIncVarIndex]);
2138             elseBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2139
2140             Value* thenPhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2141             thenThenResult->setPhi(thenPhi);
2142             elseThenResult->setPhi(thenPhi);
2143             vars[thenIncVarIndex] = thenPhi;
2144         
2145             Value* elsePhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2146             thenElseResult->setPhi(elsePhi);
2147             elseElseResult->setPhi(elsePhi);
2148             vars[elseIncVarIndex] = thenPhi;
2149         
2150             current = continuation;
2151         } else {
2152             // Loop.
2153
2154             BasicBlock* loopEntry = proc.addBlock();
2155             BasicBlock* loopReentry = proc.addBlock();
2156             BasicBlock* loopBody = proc.addBlock();
2157             BasicBlock* loopExit = proc.addBlock();
2158             BasicBlock* loopSkip = proc.addBlock();
2159             BasicBlock* continuation = proc.addBlock();
2160         
2161             Value* startIndex = vars[((i >> 1) + 1) % numVars];
2162             Value* startSum = current->appendNew<Const32Value>(proc, Origin(), 0);
2163             current->appendNewControlValue(
2164                 proc, Branch, Origin(), startIndex,
2165                 FrequentedBlock(loopEntry), FrequentedBlock(loopSkip));
2166
2167             UpsilonValue* startIndexForBody = loopEntry->appendNew<UpsilonValue>(
2168                 proc, Origin(), startIndex);
2169             UpsilonValue* startSumForBody = loopEntry->appendNew<UpsilonValue>(
2170                 proc, Origin(), startSum);
2171             loopEntry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody));
2172
2173             Value* bodyIndex = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
2174             startIndexForBody->setPhi(bodyIndex);
2175             Value* bodySum = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
2176             startSumForBody->setPhi(bodySum);
2177             Value* newBodyIndex = loopBody->appendNew<Value>(proc, Sub, Origin(), bodyIndex, one);
2178             Value* newBodySum = loopBody->appendNew<Value>(
2179                 proc, Add, Origin(),
2180                 bodySum,
2181                 loopBody->appendNew<MemoryValue>(
2182                     proc, Load, Int32, Origin(),
2183                     loopBody->appendNew<Value>(
2184                         proc, Add, Origin(),
2185                         loopBody->appendNew<ConstPtrValue>(proc, Origin(), varSlots.data()),
2186                         loopBody->appendNew<Value>(
2187                             proc, Shl, Origin(),
2188                             loopBody->appendNew<Value>(
2189                                 proc, ZExt32, Origin(),
2190                                 loopBody->appendNew<Value>(
2191                                     proc, BitAnd, Origin(),
2192                                     newBodyIndex,
2193                                     loopBody->appendNew<Const32Value>(
2194                                         proc, Origin(), numVars - 1))),
2195                             loopBody->appendNew<Const32Value>(proc, Origin(), 2)))));
2196             loopBody->appendNewControlValue(
2197                 proc, Branch, Origin(), newBodyIndex,
2198                 FrequentedBlock(loopReentry), FrequentedBlock(loopExit));
2199
2200             loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodyIndex, bodyIndex);
2201             loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodySum, bodySum);
2202             loopReentry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody));
2203
2204             UpsilonValue* exitSum = loopExit->appendNew<UpsilonValue>(proc, Origin(), newBodySum);
2205             loopExit->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2206
2207             UpsilonValue* skipSum = loopSkip->appendNew<UpsilonValue>(proc, Origin(), startSum);
2208             loopSkip->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2209
2210             Value* finalSum = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2211             exitSum->setPhi(finalSum);
2212             skipSum->setPhi(finalSum);
2213
2214             current = continuation;
2215             vars[((i >> 1) + 0) % numVars] = finalSum;
2216         }
2217     }
2218
2219     current->appendNewControlValue(proc, Return, Origin(), vars[0]);
2220
2221     compileProc(proc);
2222
2223     MonotonicTime after = MonotonicTime::now();
2224     dataLog(toCString("    That took ", (after - before).milliseconds(), " ms.\n"));
2225 }
2226
2227 void testBranchBitTest32TmpImm(uint32_t value, uint32_t imm)
2228 {
2229     Procedure proc;
2230     BasicBlock* root = proc.addBlock();
2231     BasicBlock* thenCase = proc.addBlock();
2232     BasicBlock* elseCase = proc.addBlock();
2233
2234     Value* testValue = root->appendNew<Value>(
2235         proc, Trunc, Origin(),
2236         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2237     Value* bitOffset = root->appendNew<Const32Value>(proc, Origin(), imm);
2238
2239     Value* one = root->appendNew<Const32Value>(proc, Origin(), 1);
2240     Value* bitTest = root->appendNew<Value>(
2241         proc, BitAnd, Origin(),
2242         root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset),
2243         one);
2244
2245     root->appendNewControlValue(
2246         proc, Branch, Origin(),
2247         bitTest,
2248         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2249
2250     thenCase->appendNewControlValue(
2251         proc, Return, Origin(),
2252         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2253
2254     elseCase->appendNewControlValue(
2255         proc, Return, Origin(),
2256         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2257
2258     auto code = compileProc(proc);
2259     CHECK_EQ(invoke<uint32_t>(*code, value), (value>>(imm%32))&1);
2260 }
2261
2262 void testBranchBitTest32AddrImm(uint32_t value, uint32_t imm)
2263 {
2264     Procedure proc;
2265     BasicBlock* root = proc.addBlock();
2266     BasicBlock* thenCase = proc.addBlock();
2267     BasicBlock* elseCase = proc.addBlock();
2268
2269     Value* testValue = root->appendNew<MemoryValue>(
2270         proc, Load, Int32, Origin(),
2271         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2272     Value* bitOffset = root->appendNew<Const32Value>(proc, Origin(), imm);
2273
2274     Value* one = root->appendNew<Const32Value>(proc, Origin(), 1);
2275     Value* bitTest = root->appendNew<Value>(
2276         proc, BitAnd, Origin(),
2277         root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset),
2278         one);
2279
2280     root->appendNewControlValue(
2281         proc, Branch, Origin(),
2282         bitTest,
2283         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2284
2285     thenCase->appendNewControlValue(
2286         proc, Return, Origin(),
2287         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2288
2289     elseCase->appendNewControlValue(
2290         proc, Return, Origin(),
2291         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2292
2293     auto code = compileProc(proc);
2294     CHECK_EQ(invoke<uint32_t>(*code, &value), (value>>(imm%32))&1);
2295 }
2296
2297 void testBranchBitTest32TmpTmp(uint32_t value, uint32_t value2)
2298 {
2299     Procedure proc;
2300     BasicBlock* root = proc.addBlock();
2301     BasicBlock* thenCase = proc.addBlock();
2302     BasicBlock* elseCase = proc.addBlock();
2303
2304     Value* testValue = root->appendNew<Value>(
2305         proc, Trunc, Origin(),
2306         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2307     Value* bitOffset = root->appendNew<Value>(
2308         proc, Trunc, Origin(),
2309         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2310
2311     Value* one = root->appendNew<Const32Value>(proc, Origin(), 1);
2312     Value* bitTest = root->appendNew<Value>(
2313         proc, BitAnd, Origin(),
2314         root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset),
2315         one);
2316
2317     root->appendNewControlValue(
2318         proc, Branch, Origin(),
2319         bitTest,
2320         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2321
2322     thenCase->appendNewControlValue(
2323         proc, Return, Origin(),
2324         thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2325
2326     elseCase->appendNewControlValue(
2327         proc, Return, Origin(),
2328         elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2329
2330     auto code = compileProc(proc);
2331     CHECK_EQ(invoke<uint32_t>(*code, value, value2), (value>>(value2%32))&1);
2332 }
2333
2334 void testBranchBitTest64TmpTmp(uint64_t value, uint64_t value2)
2335 {
2336     Procedure proc;
2337     BasicBlock* root = proc.addBlock();
2338     BasicBlock* thenCase = proc.addBlock();
2339     BasicBlock* elseCase = proc.addBlock();
2340
2341     Value* testValue = root->appendNew<Value>(proc, BitXor, Origin(),
2342         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2343         root->appendNew<Const64Value>(proc, Origin(), -1l));
2344     Value* bitOffset = root->appendNew<Value>(
2345         proc, Trunc, Origin(),
2346         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2347
2348     Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2349     Value* bitTest = root->appendNew<Value>(
2350         proc, BitAnd, Origin(),
2351         testValue,
2352         root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset));
2353
2354     root->appendNewControlValue(
2355         proc, Branch, Origin(),
2356         bitTest,
2357         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2358
2359     thenCase->appendNewControlValue(
2360         proc, Return, Origin(),
2361         thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2362
2363     elseCase->appendNewControlValue(
2364         proc, Return, Origin(),
2365         elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2366
2367     auto code = compileProc(proc);
2368     CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2369 }
2370
2371 void testBranchBitTest64AddrTmp(uint64_t value, uint64_t value2)
2372 {
2373     Procedure proc;
2374     BasicBlock* root = proc.addBlock();
2375     BasicBlock* thenCase = proc.addBlock();
2376     BasicBlock* elseCase = proc.addBlock();
2377
2378     Value* testValue = root->appendNew<MemoryValue>(
2379         proc, Load, Int64, Origin(),
2380         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2381     Value* bitOffset = root->appendNew<Value>(
2382         proc, Trunc, Origin(),
2383         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2384
2385     Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2386     Value* bitTest = root->appendNew<Value>(
2387         proc, BitAnd, Origin(),
2388         testValue,
2389         root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset));
2390
2391     root->appendNewControlValue(
2392         proc, Branch, Origin(),
2393         bitTest,
2394         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2395
2396     thenCase->appendNewControlValue(
2397         proc, Return, Origin(),
2398         thenCase->appendNew<Const64Value>(proc, Origin(), 1));
2399
2400     elseCase->appendNewControlValue(
2401         proc, Return, Origin(),
2402         elseCase->appendNew<Const64Value>(proc, Origin(), 0));
2403
2404     auto code = compileProc(proc);
2405     CHECK_EQ(invoke<uint64_t>(*code, &value, value2), (value>>(value2%64))&1);
2406 }
2407
2408 void testBranchBitTestNegation(uint64_t value, uint64_t value2)
2409 {
2410     Procedure proc;
2411     BasicBlock* root = proc.addBlock();
2412     BasicBlock* thenCase = proc.addBlock();
2413     BasicBlock* elseCase = proc.addBlock();
2414
2415     Value* testValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2416     Value* bitOffset = root->appendNew<Value>(
2417         proc, Trunc, Origin(),
2418         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2419     Value* shift = root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset);
2420
2421     Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2422     Value* bitTest = root->appendNew<Value>(
2423         proc, BitAnd, Origin(),
2424         root->appendNew<Value>(proc, BitXor, Origin(), shift, root->appendNew<Const64Value>(proc, Origin(), -1l)),
2425         one);
2426
2427     root->appendNewControlValue(
2428         proc, Branch, Origin(),
2429         bitTest,
2430         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2431
2432     thenCase->appendNewControlValue(
2433         proc, Return, Origin(),
2434         thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2435
2436     elseCase->appendNewControlValue(
2437         proc, Return, Origin(),
2438         elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2439
2440     auto code = compileProc(proc);
2441     CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2442 }
2443
2444 void testBranchBitTestNegation2(uint64_t value, uint64_t value2)
2445 {
2446     Procedure proc;
2447     BasicBlock* root = proc.addBlock();
2448     BasicBlock* thenCase = proc.addBlock();
2449     BasicBlock* elseCase = proc.addBlock();
2450
2451     Value* testValue = root->appendNew<Value>(proc, BitXor, Origin(),
2452         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2453         root->appendNew<Const64Value>(proc, Origin(), -1l));
2454     Value* bitOffset = root->appendNew<Value>(
2455         proc, Trunc, Origin(),
2456         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2457     Value* shift = root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset);
2458
2459     Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2460     Value* bitTest = root->appendNew<Value>(
2461         proc, BitAnd, Origin(),
2462         shift,
2463         one);
2464
2465     root->appendNewControlValue(
2466         proc, Branch, Origin(),
2467         bitTest,
2468         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2469
2470     thenCase->appendNewControlValue(
2471         proc, Return, Origin(),
2472         thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2473
2474     elseCase->appendNewControlValue(
2475         proc, Return, Origin(),
2476         elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2477
2478     auto code = compileProc(proc);
2479     CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2480 }
2481
2482 void testSimplePatchpoint()
2483 {
2484     Procedure proc;
2485     BasicBlock* root = proc.addBlock();
2486     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2487     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2488     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2489     patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
2490     patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
2491     patchpoint->setGenerator(
2492         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2493             AllowMacroScratchRegisterUsage allowScratch(jit);
2494             CHECK(params.size() == 3);
2495             CHECK(params[0].isGPR());
2496             CHECK(params[1].isGPR());
2497             CHECK(params[2].isGPR());
2498             add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2499         });
2500     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2501
2502     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2503 }
2504
2505 void testSimplePatchpointWithoutOuputClobbersGPArgs()
2506 {
2507     Procedure proc;
2508     BasicBlock* root = proc.addBlock();
2509     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2510     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2511     Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
2512     Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
2513
2514     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
2515     patchpoint->clobberLate(RegisterSet(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1));
2516     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2517     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2518     patchpoint->setGenerator(
2519         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2520             AllowMacroScratchRegisterUsage allowScratch(jit);
2521             CHECK(params.size() == 2);
2522             CHECK(params[0].isGPR());
2523             CHECK(params[1].isGPR());
2524             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[0].gpr());
2525             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[1].gpr());
2526             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR0);
2527             jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR1);
2528         });
2529
2530     Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
2531     root->appendNewControlValue(proc, Return, Origin(), result);
2532
2533     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2534 }
2535
2536 void testSimplePatchpointWithOuputClobbersGPArgs()
2537 {
2538     // We can't predict where the output will be but we want to be sure it is not
2539     // one of the clobbered registers which is a bit hard to test.
2540     //
2541     // What we do is force the hand of our register allocator by clobbering absolutely
2542     // everything but 1. The only valid allocation is to give it to the result and
2543     // spill everything else.
2544
2545     Procedure proc;
2546     if (proc.optLevel() < 1) {
2547         // FIXME: Air O0 allocator can't handle such programs. We rely on WasmAirIRGenerator
2548         // to not use any such constructs where the register allocator is cornered in such
2549         // a way.
2550         // https://bugs.webkit.org/show_bug.cgi?id=194633
2551         return;
2552     }
2553     BasicBlock* root = proc.addBlock();
2554     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2555     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2556     Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
2557     Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
2558
2559     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin());
2560
2561     RegisterSet clobberAll = RegisterSet::allGPRs();
2562     clobberAll.exclude(RegisterSet::stackRegisters());
2563     clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
2564     clobberAll.clear(GPRInfo::argumentGPR2);
2565     patchpoint->clobberLate(clobberAll);
2566
2567     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2568     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2569
2570     patchpoint->setGenerator(
2571         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2572             AllowMacroScratchRegisterUsage allowScratch(jit);
2573             CHECK(params.size() == 3);
2574             CHECK(params[0].isGPR());
2575             CHECK(params[1].isGPR());
2576             CHECK(params[2].isGPR());
2577             jit.move(params[1].gpr(), params[0].gpr());
2578             jit.add64(params[2].gpr(), params[0].gpr());
2579
2580             clobberAll.forEach([&] (Reg reg) {
2581                 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), reg.gpr());
2582             });
2583         });
2584
2585     Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
2586         root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
2587     root->appendNewControlValue(proc, Return, Origin(), result);
2588
2589     CHECK(compileAndRun<int>(proc, 1, 2) == 58);
2590 }
2591
2592 void testSimplePatchpointWithoutOuputClobbersFPArgs()
2593 {
2594     Procedure proc;
2595     BasicBlock* root = proc.addBlock();
2596     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2597     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2598     Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
2599     Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
2600
2601     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
2602     patchpoint->clobberLate(RegisterSet(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1));
2603     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2604     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2605     patchpoint->setGenerator(
2606         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2607             AllowMacroScratchRegisterUsage allowScratch(jit);
2608             CHECK(params.size() == 2);
2609             CHECK(params[0].isFPR());
2610             CHECK(params[1].isFPR());
2611             jit.moveZeroToDouble(params[0].fpr());
2612             jit.moveZeroToDouble(params[1].fpr());
2613             jit.moveZeroToDouble(FPRInfo::argumentFPR0);
2614             jit.moveZeroToDouble(FPRInfo::argumentFPR1);
2615         });
2616
2617     Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
2618     root->appendNewControlValue(proc, Return, Origin(), result);
2619
2620     CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 4);
2621 }
2622
2623 void testSimplePatchpointWithOuputClobbersFPArgs()
2624 {
2625     Procedure proc;
2626     if (proc.optLevel() < 1) {
2627         // FIXME: Air O0 allocator can't handle such programs. We rely on WasmAirIRGenerator
2628         // to not use any such constructs where the register allocator is cornered in such
2629         // a way.
2630         // https://bugs.webkit.org/show_bug.cgi?id=194633
2631         return;
2632     }
2633     BasicBlock* root = proc.addBlock();
2634     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2635     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2636     Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
2637     Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
2638
2639     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin());
2640
2641     RegisterSet clobberAll = RegisterSet::allFPRs();
2642     clobberAll.exclude(RegisterSet::stackRegisters());
2643     clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
2644     clobberAll.clear(FPRInfo::argumentFPR2);
2645     patchpoint->clobberLate(clobberAll);
2646
2647     patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2648     patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2649
2650     patchpoint->setGenerator(
2651         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2652             AllowMacroScratchRegisterUsage allowScratch(jit);
2653             CHECK(params.size() == 3);
2654             CHECK(params[0].isFPR());
2655             CHECK(params[1].isFPR());
2656             CHECK(params[2].isFPR());
2657             jit.addDouble(params[1].fpr(), params[2].fpr(), params[0].fpr());
2658
2659             clobberAll.forEach([&] (Reg reg) {
2660                 jit.moveZeroToDouble(reg.fpr());
2661             });
2662         });
2663
2664     Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
2665         root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
2666     root->appendNewControlValue(proc, Return, Origin(), result);
2667
2668     CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6);
2669 }
2670
2671 void testPatchpointWithEarlyClobber()
2672 {
2673     auto test = [] (GPRReg registerToClobber, bool arg1InArgGPR, bool arg2InArgGPR) {
2674         Procedure proc;
2675         BasicBlock* root = proc.addBlock();
2676         Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2677         Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2678     
2679         PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2680         patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
2681         patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
2682         patchpoint->clobberEarly(RegisterSet(registerToClobber));
2683         unsigned optLevel = proc.optLevel();
2684         patchpoint->setGenerator(
2685             [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2686                 if (optLevel > 1) {
2687                     CHECK((params[1].gpr() == GPRInfo::argumentGPR0) == arg1InArgGPR);
2688                     CHECK((params[2].gpr() == GPRInfo::argumentGPR1) == arg2InArgGPR);
2689                 }
2690             
2691                 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2692             });
2693
2694         root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2695
2696         CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2697     };
2698
2699     test(GPRInfo::nonArgGPR0, true, true);
2700     test(GPRInfo::argumentGPR0, false, true);
2701     test(GPRInfo::argumentGPR1, true, false);
2702 }
2703
2704 void testPatchpointCallArg()
2705 {
2706     Procedure proc;
2707     BasicBlock* root = proc.addBlock();
2708     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2709     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2710     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2711     patchpoint->append(ConstrainedValue(arg1, ValueRep::stackArgument(0)));
2712     patchpoint->append(ConstrainedValue(arg2, ValueRep::stackArgument(8)));
2713     patchpoint->setGenerator(
2714         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2715             AllowMacroScratchRegisterUsage allowScratch(jit);
2716             CHECK(params.size() == 3);
2717             CHECK(params[0].isGPR());
2718             CHECK(params[1].isStack());
2719             CHECK(params[2].isStack());
2720             jit.load32(
2721                 CCallHelpers::Address(GPRInfo::callFrameRegister, params[1].offsetFromFP()),
2722                 params[0].gpr());
2723             jit.add32(
2724                 CCallHelpers::Address(GPRInfo::callFrameRegister, params[2].offsetFromFP()),
2725                 params[0].gpr());
2726         });
2727     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2728
2729     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2730 }
2731
2732 void testPatchpointFixedRegister()
2733 {
2734     Procedure proc;
2735     BasicBlock* root = proc.addBlock();
2736     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2737     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2738     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2739     patchpoint->append(ConstrainedValue(arg1, ValueRep(GPRInfo::regT0)));
2740     patchpoint->append(ConstrainedValue(arg2, ValueRep(GPRInfo::regT1)));
2741     patchpoint->setGenerator(
2742         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2743             AllowMacroScratchRegisterUsage allowScratch(jit);
2744             CHECK(params.size() == 3);
2745             CHECK(params[0].isGPR());
2746             CHECK(params[1] == ValueRep(GPRInfo::regT0));
2747             CHECK(params[2] == ValueRep(GPRInfo::regT1));
2748             add32(jit, GPRInfo::regT0, GPRInfo::regT1, params[0].gpr());
2749         });
2750     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2751
2752     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2753 }
2754
2755 void testPatchpointAny(ValueRep rep)
2756 {
2757     Procedure proc;
2758     BasicBlock* root = proc.addBlock();
2759     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2760     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2761     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2762     patchpoint->append(ConstrainedValue(arg1, rep));
2763     patchpoint->append(ConstrainedValue(arg2, rep));
2764     patchpoint->setGenerator(
2765         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2766             AllowMacroScratchRegisterUsage allowScratch(jit);
2767             // We shouldn't have spilled the inputs, so we assert that they're in registers.
2768             CHECK(params.size() == 3);
2769             CHECK(params[0].isGPR());
2770             CHECK(params[1].isGPR());
2771             CHECK(params[2].isGPR());
2772             add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2773         });
2774     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2775
2776     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2777 }
2778
2779 void testPatchpointGPScratch()
2780 {
2781     Procedure proc;
2782     BasicBlock* root = proc.addBlock();
2783     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2784     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2785     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2786     patchpoint->append(arg1, ValueRep::SomeRegister);
2787     patchpoint->append(arg2, ValueRep::SomeRegister);
2788     patchpoint->numGPScratchRegisters = 2;
2789     patchpoint->setGenerator(
2790         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2791             AllowMacroScratchRegisterUsage allowScratch(jit);
2792             // We shouldn't have spilled the inputs, so we assert that they're in registers.
2793             CHECK(params.size() == 3);
2794             CHECK(params[0].isGPR());
2795             CHECK(params[1].isGPR());
2796             CHECK(params[2].isGPR());
2797             CHECK(params.gpScratch(0) != InvalidGPRReg);
2798             CHECK(params.gpScratch(0) != params[0].gpr());
2799             CHECK(params.gpScratch(0) != params[1].gpr());
2800             CHECK(params.gpScratch(0) != params[2].gpr());
2801             CHECK(params.gpScratch(1) != InvalidGPRReg);
2802             CHECK(params.gpScratch(1) != params.gpScratch(0));
2803             CHECK(params.gpScratch(1) != params[0].gpr());
2804             CHECK(params.gpScratch(1) != params[1].gpr());
2805             CHECK(params.gpScratch(1) != params[2].gpr());
2806             CHECK(!params.unavailableRegisters().get(params.gpScratch(0)));
2807             CHECK(!params.unavailableRegisters().get(params.gpScratch(1)));
2808             add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2809         });
2810     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2811
2812     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2813 }
2814
2815 void testPatchpointFPScratch()
2816 {
2817     Procedure proc;
2818     BasicBlock* root = proc.addBlock();
2819     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2820     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2821     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2822     patchpoint->append(arg1, ValueRep::SomeRegister);
2823     patchpoint->append(arg2, ValueRep::SomeRegister);
2824     patchpoint->numFPScratchRegisters = 2;
2825     patchpoint->setGenerator(
2826         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2827             AllowMacroScratchRegisterUsage allowScratch(jit);
2828             // We shouldn't have spilled the inputs, so we assert that they're in registers.
2829             CHECK(params.size() == 3);
2830             CHECK(params[0].isGPR());
2831             CHECK(params[1].isGPR());
2832             CHECK(params[2].isGPR());
2833             CHECK(params.fpScratch(0) != InvalidFPRReg);
2834             CHECK(params.fpScratch(1) != InvalidFPRReg);
2835             CHECK(params.fpScratch(1) != params.fpScratch(0));
2836             CHECK(!params.unavailableRegisters().get(params.fpScratch(0)));
2837             CHECK(!params.unavailableRegisters().get(params.fpScratch(1)));
2838             add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2839         });
2840     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2841
2842     CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2843 }
2844
2845 void testPatchpointLotsOfLateAnys()
2846 {
2847     Procedure proc;
2848     BasicBlock* root = proc.addBlock();
2849     Vector<int> things;
2850     for (unsigned i = 200; i--;)
2851         things.append(i);
2852
2853     Vector<Value*> values;
2854     for (int& thing : things) {
2855         Value* value = root->appendNew<MemoryValue>(
2856             proc, Load, Int32, Origin(),
2857             root->appendNew<ConstPtrValue>(proc, Origin(), &thing));
2858         values.append(value);
2859     }
2860
2861     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2862     patchpoint->clobber(RegisterSet::macroScratchRegisters());
2863     for (Value* value : values)
2864         patchpoint->append(ConstrainedValue(value, ValueRep::LateColdAny));
2865     patchpoint->setGenerator(
2866         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2867             AllowMacroScratchRegisterUsage allowScratch(jit);
2868             // We shouldn't have spilled the inputs, so we assert that they're in registers.
2869             CHECK(params.size() == things.size() + 1);
2870             CHECK(params[0].isGPR());
2871             jit.move(CCallHelpers::TrustedImm32(0), params[0].gpr());
2872             for (unsigned i = 1; i < params.size(); ++i) {
2873                 if (params[i].isGPR()) {
2874                     CHECK(params[i] != params[0]);
2875                     jit.add32(params[i].gpr(), params[0].gpr());
2876                 } else {
2877                     CHECK(params[i].isStack());
2878                     jit.add32(CCallHelpers::Address(GPRInfo::callFrameRegister, params[i].offsetFromFP()), params[0].gpr());
2879                 }
2880             }
2881         });
2882     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2883
2884     CHECK(static_cast<size_t>(compileAndRun<int>(proc)) == (things.size() * (things.size() - 1)) / 2);
2885 }
2886
2887 void testPatchpointAnyImm(ValueRep rep)
2888 {
2889     Procedure proc;
2890     BasicBlock* root = proc.addBlock();
2891     Value* arg1 = root->appendNew<Value>(
2892         proc, Trunc, Origin(),
2893         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2894     Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
2895     PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2896     patchpoint->append(ConstrainedValue(arg1, rep));
2897     patchpoint->append(ConstrainedValue(arg2, rep));
2898     patchpoint->setGenerator(
2899         [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2900             AllowMacroScratchRegisterUsage allowScratch(jit);
2901             CHECK(params.size() == 3);
2902             CHECK(params[0].isGPR());
2903             CHECK(params[1].isGPR());
2904             CHECK(params[2].isConstant());
2905             CHECK(params[2].value() == 42);
2906             jit.add32(
2907                 CCallHelpers::TrustedImm32(static_cast<int32_t>(params[2].value())),
2908                 params[1].gpr(), params[0].gpr());
2909         });
2910     root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2911
2912     CHECK(compileAndRun<int>(proc, 1) == 43);
2913 }
2914
2915 #endif // ENABLE(B3_JIT)